让我们考虑一下非常简短的代码片段:
#include <stdlib.h>
int main()
{
char* a = malloc(20000);
char* b = realloc(a, 5);
free(b);
return 0;
}
在阅读realloc的手册页后,我不完全确定第二行会导致释放19995个额外字节。引用手册页:The realloc() function changes the size of the memory block pointed to by ptr to size bytes.
,但根据该定义,我可以确定其余的将被释放吗?
我的意思是,b
指向的块肯定包含5个空闲字节,所以对于懒惰的顺从分配器是否足以为realloc线做任何事情都不够?
注意:我使用的分配器似乎释放了19 995个额外字节,如valgrind在注释free(b)
行时所示:
==4457== HEAP SUMMARY:
==4457== in use at exit: 5 bytes in 1 blocks
==4457== total heap usage: 2 allocs, 1 frees, 20,005 bytes allocated
答案 0 :(得分:24)
是的,如果可以分配新对象,则由C标准保证。
(C99,7.20.3.4p2)“realloc函数释放ptr指向的旧对象,并返回一个指向大小指定大小的新对象的指针。”
答案 1 :(得分:19)
是的 - 如果成功的话。
您的代码段显示了一个众所周知的恶意错误:
char* b = (char*) realloc(a, 5);
如果成功,将释放先前分配给a
的内存,b
将指向可能与原始块重叠或不重叠的5个字节的内存。
但是,如果通话失败,b
将为null
,但a
仍将指向其原始内存,该内存仍然有效。在这种情况下,您需要free(a)
才能释放内存。
如果你使用常见的(危险的)习语,那就更糟了:
a = realloc(a, NEW_SIZE); // Don't do this!
如果对realloc
的调用失败,则a将为null
,其原始内存将被孤立,使其无法恢复,直到您的程序退出。
答案 2 :(得分:3)
这取决于你的libc实现。以下所有内容都符合以下行为:
也可以
在这种情况下,旧数据也将保持原样,这可能导致内存泄漏,例如,如果realloc()
的返回值覆盖指向该块的指针的唯一副本。
合理的libc实现将使用一些启发式方法来确定哪种解决方案最有效。
另请注意,此描述处于实现级别:从语义上讲,只要分配没有失败,realloc()
就会释放对象。
答案 3 :(得分:1)
realloc函数具有以下合同:
void * result = realloc(ptr,new_size)
引擎盖下的内容的具体细节是特定于实现的 - 例如结果可能等于ptr(但不能再触及new_size之外的额外空间)并且realloc可以自由调用,或者可以自己执行内部操作自由代表。关键是作为开发人员,如果realloc返回非null,则不再对ptr负责,并且如果realloc返回NULL,则仍然对此负责。
答案 4 :(得分:0)
似乎不太可能释放19995个字节。 更有可能的是,realloc用另外的5字节块替换了20000字节的块, 也就是说,释放了20000字节的块,并分配了一个新的5字节块。