realloc后的空闲内存如何

在此代码中释放内存的正确方法是什么?

#include  #include  #include  int main( void ){ char *string1, *string2; string1 = (char*) malloc(16); strcpy(string1, "0123456789AB"); string2 = realloc(string1, 8); printf("string1 Valor: %p [%s]\n", string1, string1); printf("string2 Valor: %p [%s]\n", string2, string2); free(string1); free(string2); return 0; } 

由于两个指针指向同一个方向

我认为你的困惑来自(无灵感)表达式“自由指针”(你在post中使用过,但自从编辑后)。 你没有自由指针 。 你释放记忆 。 指针只是告诉哪个内存。


在你的例子中,你有:从malloc获得的mallocstring1指向此内存。 然后当你调用realloc时,会获得一个新的内存块(可能从相同的地址开始,可能不是),但是realloc会在需要时注意释放旧的内存块(因此是未定义的访问行为或自己释放它)。 string2指向这个新的内存块。

所以你必须freerealloc获得的内存块。 string2指向那个内存。

总之,没有。

根据C标准 :

7.22.3.5 reallocfunction

realloc函数解除分配ptr指向的旧对象,并返回指向具有size指定size 的新对象的指针 。 新对象的内容应与解除分配之前的旧对象的内容相同,直到新旧大小中的较小者为止。 新对象中超出旧对象大小的任何字节都具有不确定的值。

一旦调用realloc() ,就不必free()传递 realloc()的指针寻址的内存 – 你必须free()由指针realloc()返回的内存。 (除非realloc()返回NULL ,在这种情况下, 原始的内存块 – 传递 realloc() – 必须是free() ‘d。)

当您调用realloc ,返回的指针与原始指针相同,或者返回一个新指针并且原始指针变为无效。 在第一种情况下,在string1string2上调用free导致双重释放,因为指针是相等的。 在第二种情况下,在string1上调用free是双重释放的,因为它已经被释放了。

所以无论哪种方式,你都有一个双重自由,导致未定义的行为 。

从realloc的手册页:

 void *realloc(void *ptr, size_t size); 

realloc()函数将ptr指向的内存块的大小更改为size字节。 内容将在从区域的开始到新旧尺寸的最小范围内保持不变。 如果新大小大于旧大小,则不会初始化添加的内存。 如果ptr为NULL,则对于所有size值,调用等效于malloc(size); 如果size等于零,并且ptr不为NULL,则调用等效于free(ptr)。 除非ptr为NULL,否则必须由之前调用malloc(),calloc()或realloc()返回。 如果指向的区域被移动,则完成自由(ptr)。

realloc()函数返回一个指向新分配的内存的指针,该内存适用于任何类型的变量,可能与ptr不同 ,如果请求失败,则返回NULL。

也可以从手册页免费获取 :

free()函数释放ptr指向的内存空间,该内存空间必须由之前调用malloc(),calloc()或realloc()返回。 否则,或者如果之前已经调用了free(ptr),则会发生未定义的行为 。 如果ptr为NULL,则不执行任何操作。

你只需要free(string2)

简短的回答:在你的代码中,调用free(string2)是正确的,并且足够了。 调用free(string1)不正确。

当你调用realloc (并假设调用成功)时,它的返回值(存储在string2 )成为引用你拥有的一块内存的唯一方法。

可能是realloc “就地”调整了内存块的大小,这意味着string2string1的值相等。 在这种情况下,调用free(string1)是错误的,因为你释放了两次相同的指针。

可能是realloc在resize的过程中将数据移动到新位置。 在这种情况下, string2string1的值不相等。 但在这种情况下,在找到数据的新位置并将其复制到那里后, realloc自动为您释放旧块 。 所以,再次调用free(string1)是错误的,因为你释放了一个已经释放的指针。

realloc视为等同于:

 void * realloc(void *old, size_t new_size) { size_t old_size = magic_internal_function_that_knows_the_size_of(old); void *new = malloc(new_size); if (new == NULL) return NULL; memcpy(new, old, new_size > old_size ? old_size : new_size); free(old); return new; } 

如果你有魔术函数可以确定指针的分配大小,你可以像这样自己实现reallocmalloc几乎必须在内部free使用此function。

realloc也可以做一些聪明的事情,比如找出你正在重新分配到一个较小的大小,只是释放你的部分分配,或者发现你正在增加你的分配,并且在适应它之后有足够的空间。 但是你不需要考虑这些情况。 认为realloc是malloc + memcpy + free不会误导你,除非你需要记住realloc失败并返回NULL意味着它没有free

realloc implicity释放输入,它可能根本不做任何事情,但你不能在重新分配内存后释放它。 所以

 char *string1, *string2; string1 = (char*) malloc(16); .... string2 = realloc(string1, 8); // this line implicitly frees string1 free(string1); // this is wrong !!! free(string2);