如何用C自由和malloc的工作?如何用C自由和malloc的工作?(How do free and

2019-05-08 20:31发布

我试图找出会发生,如果我尝试释放“从中间”比如一个指针,看看下面的代码:

char *ptr = (char*)malloc(10*sizeof(char));

for (char i=0 ; i<10 ; ++i)
{
    ptr[i] = i+10;
}
++ptr;
++ptr;
++ptr;
++ptr;
free(ptr);

我得到一个未处理的异常错误味精崩溃。 我想知道为什么和如何免费工作,这样我不仅知道如何使用它,但也能理解奇怪的错误和异常,更好地调试我的代码ץ

非常感谢

Answer 1:

当你的malloc块,它实际上分配更多的内存比你自找的。 这额外的内存用来存储信息,如已分配块的大小,以块链到下一个空闲/使用区块的链接,有时一些“保护数据”,帮助系统,如果你写过去检测您的分配块的结尾。 此外,大多数分配器会总结的总尺寸和/或您的存储器的一部分的字节的倍数(例如,64位的系统上可以对齐数据以64位(8个字节),为多个启动从非对齐的地址访问数据可以是更加困难和低效率的用于在处理器/总线),因此也可与一些“填充”(未使用的字节)结束。

当你释放你的指针,它使用该地址找到它添加到您的分配块的开始(通常)的特殊信息。 如果您在不同的转交地址,它将访问包含垃圾内存,因此其行为是不确定的(但最经常会导致崩溃)

以后,如果您免费()块,但没有“忘记”您的指针,你可能会意外地尝试通过该指针在未来的访问数据,而行为是不确定的。 凡有下列情况可能发生:

  • 记忆可能被放入空闲块的列表,所以当你访问它,它仍然恰好包含你离开了那里的数据,你的代码运行正常。
  • 内存分配器可以给(的一部分)的内存的程序的其他部分,这将有可能随后将覆盖(部分)的旧数据,所以当你读它,你会得到垃圾这可能会导致意外的行为或者从你的代码崩溃。 或者你会写在其它数据,使你的程序在未来的某个时候奇怪的行为的其他部分。
  • 记忆可能已经返回到操作系统(“页”的内存,你不再使用可以从您的地址空间中删除,因此不再在该地址可用任何内存 - 本质上是一个未使用的“洞”在您的应用程序的内存)。 当应用程序试图访问数据就会产生硬内存故障并杀死你的进程。

这就是为什么要确保你释放它指向内存后不使用指针是很重要的 - 最好的做法,这是释放内存后设置指针为NULL,因为你可以很容易地测试NULL,和试图通过NULL指针访问内存会造成不好的,但一致的行为,这是更易于调试。



Answer 2:

你可能知道,你应该回传正是你收到的指针。

由于免费()起初不知道你的块有多大,它需要以从地址识别原始块,然后将其返回到空闲列表辅助信息。 它也将尝试以产生更有价值的大空闲块合并与邻居小释放的块。

最终,分配器必须对您的块的元数据,它至少需要有地方存储长度。

我将介绍三种方法可以做到这一点。

  • 一个明显的地方将它存储只是返回的指针之前。 它可以分配一块比要求的大的几个字节,大小存放在第一个字,然后返回一个指向你的第二个字。

  • 另一种方法是,以保持描述分配的块中的至少长度的单独的地图,使用地址作为密钥。

  • 实现可能获得来自地址从地图的一些信息和一些。 在4.3BSD内核分配器(叫,我想,“McKusick-卡雷尔分配器”),使幂的两笔拨款超过页面大小的物体较小且只保留每个页面的大小,从给定的页面使所有分配单一尺寸。

这将有可能与某些类型的第二次,或许任何第三类分配的实际检测,你有先进的指针和DTRT ,但我怀疑,如果任何执行会燃烧运行时这样做。



Answer 3:

大部分(如果不是全部)实施,将查找的数据量你操纵的实际指针之前释放几个字节。 做一个野生free会导致内存映射腐败。

如果你的榜样,当你分配10个字节的内存,系统实际储备,比方说,14第4包含了你请求的数据(10)的量,然后返回值malloc是一个指向第一个字节在14的未使用的数据分配。

当您拨打free这个指针,系统将查找4个字节向后知道它最初分配的14个字节,使其知道多少自由。 该系统会阻止您提供的数据量,以自由作为一个额外的参数来free自己。

当然,其他实施malloc / free可以选择其他的方式来实现这一目标。 但他们一般不支持free在不同的指针比被返回malloc或同等功能。



Answer 4:

从http://opengroup.org/onlinepubs/007908775/xsh/free.html

自由()函数使得空间ptr指向被解除分配; 也就是说,对于进一步分配可用。 若ptr为空指针,不会发生任何操作。 否则,如果该参数不匹配的指针早些时候释放calloc(),malloc()函数,realloc的()或valloc()函数返回,或者如果空间是通过调用释放释放()或realloc()时,行为是不确定的。 任何使用是指释放的空间指针会导致不确定的行为。



Answer 5:

这是不确定的行为 - 不这样做。 只有free()从获得的指针malloc()从未在此之前,对其进行调整。

问题是free()必须非常快,所以它不会尝试找到你的调整后的地址属于分配,而是试图在精确调整后的地址返回块堆。 这导致不确定的行为 - 通常堆损坏或崩溃的程序。



Answer 6:

你释放了错误的地址。 通过改变PTR的值,可以更改地址。 免费有没有办法知道,应该尽量免费启动4个字节回块的方式。 保持原有的指针完整和自由,代替操纵之一。 正如其他人所指出的,做你正在做的事情的结果是“不确定” ......因此,未处理的异常。



Answer 7:

从来没有做到这一点。

你释放了错误的地址。 通过改变PTR的值,可以更改地址。 免费有没有办法知道,应该尽量免费启动4个字节回块的方式。 保持原有的指针完整和自由,代替操纵之一。 正如其他人所指出的,做你正在做的事情的结果是“不确定” ......因此,未处理的异常



Answer 8:

从书摘自: 理解和使用C指针,指向

当存储器被分配,附加信息被存储为由堆管理器维护的数据结构的一部分。 该信息包括,除了别的以外,块的尺寸,并且通常立即置于邻近所述分配的块。



文章来源: How do free and malloc work in C?