是否有一些“可自由”的记忆

时间:2011-07-05 13:03:01

标签: c pointers memory-management malloc free

int main()
{
    char *s1, *sTemp;

    s1 = (char*)malloc(sizeof(char)*7);
    *(s1 + 0) = 'a';
    *(s1 + 1) = 'b';
    *(s1 + 2) = 'c';
    *(s1 + 3) = 'd';
    *(s1 + 4) = 'e';
    *(s1 + 5) = 'f';
    *(s1 + 6) = '\0';

    sTemp = (s1 + 3);

    free(sTemp); // shud delete d onwards. But it doesn't !!

    return 0;
}

您好,

C 上面,代码sTemp应指向s1以外的第3个单元格(由'd'占用) 因此,在致电free(sTemp)时,我希望从此位置开始删除

(我故意提到' 某事 ',因为我的实验的动机最初是找出free()ing工作的位置)

但是我在SIGABRT收到free()

free()如何知道这不是块的开头。相应地,我们只能从块的开始释放内存吗? [他们只是free()可以接受的自由指针吗? ]

期待回复:)

6 个答案:

答案 0 :(得分:7)

从手册页

  

free()释放指向的内存空间   到ptr,一定是   之前的电话回复   malloc()calloc()realloc()。   否则,或者free(ptr)已经存在   以前被称为未定义   行为发生。

来源:http://linux.die.net/man/3/free

答案 1 :(得分:3)

关于实际问题“free如何知道......”:

free知道它不在块的开头,因为它维护着你不知道的元数据。如果你考虑一下,那就是必然那么,因为否则它只能在一个地址的情况下知道要释放多少内存。

没有指定运行时如何保持分配大小,只是你必须永远传递任何 not 来自free的指针malloc家庭的一个功能。

通常这可以通过malloc分配比所需 [1] 更多的内存,并在内存前面返回的地址中写入一些元数据。 free然后只看例如ptr[-8]或其他(实现细节!)来阅读此元数据 然后它可以选择进行一些一致性检查,并且可以确定内存块的大小(可能总是进行一次微不足道的一致性检查,检查指针是否正确对齐)。

在提到之后,请讨好,甚至不要考虑使用这个元数据。


[1] 无论如何它通常都是为了满足对齐要求,并且因为分配器内部(大多数分配器管理固定大小的不同“桶”中的内存),所以如果分配,比方说,4字节,你名义上得到4个字节,但运行时大部分时间确实分配了8或16个字节(你不知道)。

答案 2 :(得分:2)

您只能free()实际malloc ed(或calloc ed,realloc ed的指针。如果你试图通过传入一个不同的指针(即使是另一个指针的“部分”)来释放一部分内存,那么C运行时将不会高兴(正如你所看到的那样)。

答案 3 :(得分:2)

我认为你无法释放内存,因为free不知道要释放多少内存。你的程序有关于地址malloc()返回的信息,而不是这个空间中的每个地址。​​所以你可以释放(s1)但是不是免费的(s1 + 3)。也可以在这个例子中将指针作为数组处理: S1 [0] = 'A';

答案 4 :(得分:1)

您只能free()以前malloccallocrealloc编辑过的realloc内存,正如dlev和Daniel所说的那样。

其原因是依赖于实现,但涉及跟踪已分配内存的方法。

高效的内存分配是一个难题,因为不同的内存分配算法可以很好地工作,具体取决于内存的分配方式:一些小块,其中一半被释放,然后抓取稍大的块等等。

目标是使程序使用的内存块的大小保持最小(通常这个块将是一个连续的虚拟内存块),同时保持该块内空间的使用率极高(几个间隙)在已用的内存段之间。)

请记住,除非free被编辑,否则无法移动这些块,因此总会留下一些浪费的空间。

为了最大限度地减少浪费,关于(至少)块大小的元数据就在它之前存储。在确定如何处理新请求时,内存分配器可以查看使用的块。如果您选择随机内存位置,无论是先前分配的区域的一部分还是否,此元数据都不会出现,{{1}}将无法确定应该释放的内容。

答案 5 :(得分:0)

你不能以你的方式释放指针,检查这个问题及其答案:Memory Clobbering Error