在此代码中释放内存的正确方法是什么?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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;
}
由于两个指针指向同一个方向
我认为你的困惑来自(无灵感)表达式“自由指针”(你在帖子中使用过,但自从编辑后)。你没有自由指针。你释放记忆。指针只是告诉哪个内存。
在你的例子中,你有:从malloc
获得的记忆。 string1
指向这个记忆。然后,当你调用realloc
时,会获得一个新的内存块(可能从相同的地址开始,可能不是),但realloc
会在需要时小心释放旧的内存块(因此是未定义的行为,可以自行访问或释放它)。 string2
指向这个新的内存块。
所以你必须free
只是从realloc
获得的内存块。 string2
指向那个记忆。
简而言之,没有。
7.22.3.5
realloc
功能...
realloc
函数释放ptr
指向的旧对象,并返回指向由size
指定大小的新对象的指针。新对象的内容应与解除分配之前的旧对象的内容相同,直到新旧大小中的较小者为止。新对象中超出旧对象大小的任何字节都具有不确定的值。
一旦你调用realloc()
,你没有free()
传递给realloc()
的指针寻址的内存 - 你必须free()
指针realloc()
返回的内存。 (除非realloc()
返回NULL
,在这种情况下,原始的内存块 - 传递给realloc()
- 必须是free()
'd。)
当您调用realloc
时,返回的指针与原始指针相同,或者返回一个新指针并且原始指针变为无效。在第一种情况下,在free
和string1
上调用string2
会导致双重释放,因为指针是相等的。在第二种情况下,在free
上调用string1
是双重免费的,因为它已经被释放了。
所以无论哪种方式,你都有一个双倍自由,导致undefined behavior。
从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的手册页:
free()函数释放ptr指向的内存空间,该内存空间必须由之前调用malloc(),calloc()或realloc()返回。否则,或者如果之前已经调用了free(ptr),则会发生未定义的行为。如果ptr为NULL,则不执行任何操作。
你只需要free(string2)
。
简短的回答:在你的代码中,调用free(string2)
是正确的,并且足够了。调用free(string1)
不正确。
当您调用realloc
(并假设调用成功)时,其返回值(存储在string2
中)成为引用您拥有的一块内存的唯一方法。
可能是realloc
“就地”调整了你的记忆块,这意味着string2
和string1
的值是相等的。在这种情况下,调用free(string1)
是错误的,因为你将两次相同的指针释放。
可能是realloc
在调整大小的过程中将您的数据移动到新的位置。在这种情况下,string2
和string1
的值是不相等的。但在这种情况下,在找到数据的新位置并将其复制到那里后,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;
}
如果你有魔术函数可以计算指针的分配大小,你可以像这样自己实现realloc
。 malloc
几乎必须在内部为free
工作。
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);