在C程序中,对于同一个指针调用“free”两次会有什么危害?

11

如果我有一个类似以下的 C 语言程序:

SomeTypePtr my_type;
my_type = malloc(sizeof(someType));

/* do stuff */

free(my_type);

/* do a bunch of more stuff */

free(my_type);

调用'free'函数会对'my_type'造成任何伤害吗?在我调用'free(my_type)'后,指针会再次变为null指针吗?


请参阅http://en.wikipedia.org/wiki/Malloc#Use_after_free。 - Rooke
4个回答

13

free释放内存区域并不会使指针内容变为NULL。假设你有int *a = malloc(sizeof(int)),且a的值为0xdeadbeef,执行free(a)后,a仍然包含0xdeadbeef,但是free调用后,该内存地址不再为您保留。这就好比你租了一套通过malloc使用的公寓一段时间,然后通过free归还了公寓,此后你可能仍然持有复制的钥匙,但是该公寓已经不再为你所保留。

对已经被free释放的内存再次进行free将导致双重释放内存破坏。


哦,非常清楚,谢谢。有没有办法检测指针所指向的内存是否已被释放? - Ash
我猜这就是为什么有些最佳实践文件建议在调用 free(pointer) 后始终手动将指针设置为 NULL - Ash
@Ash:看一下这篇帖子:https://dev59.com/ym855IYBdhLWcg3wy3kb - phoxis
一定要将未使用的指针赋值为NULL。这样可以帮助你通过“if-else”语句来确定哪一个是未使用的。 - phoxis
@phoxis:我不同意:这将防止您意识到指针已被多次释放,这几乎总是一个错误。 - titaniumdecoy
取决于您正在实现什么。如果您正在实现链表,则将最后一个指针分配为NULL是最好的选择。对于确定多个释放,是的,这也是一个要点。 - phoxis

4
  1. 它不会使你的指针变成NULL。
  2. 它会释放指针所指向的内存,但是指针会指向一块未分配的内存。
  3. 如果在两次调用之间没有使用malloc或calloc,则会导致Segmentation Fault。
  4. "最佳实践是指针在被释放后立即超出作用域"意味着指针应该保留在堆栈中,因此不应明确将其设置为NULL,因为它最终会超出作用域并被释放。

4
如果你很幸运的话,它会产生一个SEGV错误。 :) - sarnold

3

不重复其他答案的内容,一旦您调用了free(),您就需要将空指针置为NULL。在同一分配上两次调用free()会导致堆损坏。

SomeTypePtr my_type;
my_type = malloc(sizeof(someType));

/* do stuff */

free(my_type);
my_type = 0; // Throw away the pointer to released memory, so cannot either free it or use it in any way.

/* do a bunch of more stuff */

free(my_type); // OK now - calling free(0) is safe.

3

只有当你认为摧毁你的堆栈是“有害”的时候,free() 才会使你的指针为空。


那么,我该如何测试指针是否已经被正确释放? - Ash
调用将始终成功,除非没有可释放的内容,否则会导致分段错误。 - Radu Stoenescu
2
我链接的维基百科文章对此有一个相当简洁但明智的答案:“最佳实践是指针在被释放后立即超出作用域。” - Rooke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接