在C语言中尝试释放已被释放的内存会发生什么?

36
例如:
char * myString = malloc(sizeof(char)*STRING_BUFFER_SIZE);
free(myString);
free(myString);

这样做会有任何不良副作用吗?

14个回答

41

以下是具体规定:

如果传递给free函数的参数与之前由callocmallocrealloc函数返回的指针不匹配,或者所释放的空间已经被freerealloc调用释放,则行为未定义。(ISO 9899:1999 - C编程语言,第7.20.3.2节)


13
FYI:当C或C++说“未定义”时,通常意味着“崩溃”、“内存损坏”或类似可怕的问题。请注意。 - Orion Edwards
15
不,他们真的是指“未定义”。这只是包括崩溃和内存损坏在内的一部分。 - Chris Conway
12
编译器可以决定启动NetHack,例如。 - remmy

20

其中之一是没有内容,另一种是静默内存损坏,还有一种是分段错误。


当您访问超出边界的内存时,会发生段错误。 - user376845

14

是的,你可能遇到双重释放错误导致程序崩溃。这与malloc内部的数据结构有关,用于跟踪已分配的内存。


9

答案概述:

是的,不好的事情可能会发生。

为了防止这种情况发生,请执行以下操作:

free(myString);
myString = NULL;

请注意,如果创建了其他引用,则所有对内存的引用都必须设置为NULL
此外,使用NULL调用free()不会产生任何作用。有关更多信息,请参见:man free

请注意,如果您已经复制了指针,则这些指针也应该设置为NULL。 - Michael Carman
似乎社区更倾向于将答案总结放在实际的问题中,而不是作为仍然被埋藏的问题。 - PhirePhly
这个想法不好,因为它不适用于常量值。你尽可能使用常量值,对吧? - Steve Jessop

6

6

不太聪明。谷歌搜索双重释放漏洞。释放后将指针设置为NULL,以避免此类错误。


很遗憾,你无法编写一个包装器来自动完成此操作,因为指针是按值传递而不是按引用传递的。例如 Free(void **p) {free(*p); *p = NULL;} 这个操作不太容易重新配置代码。 - jbleners
使用宏定义:#define freep(x) (free(x); x = 0;) - Derek Park
这个想法不太好,因为它不适用于const值。你会尽可能使用const值,对吧? - Steve Jessop
@Steve:我知道这个问题很老了,但是我们在其他地方讨论过传递一个const限定的指针给free函数是无效的(从概念上和形式上都是如此,除非你强制转换去掉限定符)吧? :-) - R.. GitHub STOP HELPING ICE
@R..:我正在谈论的是char *const ptr = malloc(STRING_BUFFER_SIZE); ... ; free(ptr);。我认为这既不是形式上也不是概念上无效的。之后,ptr = 0;也不可能了。因此,如果您像Derek所说定义了一个宏freep,那么您不能在ptr上使用它。 - Steve Jessop

5

根据运行的系统不同,可能会发生以下情况:什么也不会发生、程序将崩溃、内存将被破坏或其他有趣的影响。


4

坏事情(TM)

实际上,我认为这是未定义的,因此可以包括与NORAD主机玩“全球热核战争”等任何事情。


3

在释放指针后,始终将其设置为NULL。尝试释放空指针是安全的。

值得编写自己的free包装器以自动执行此操作。


你的free()包装器必须是一个宏,或者必须使用与标准free()函数不同的接口。 - Jonathan Leffler

2

不要这样做。如果在调用free之间将被释放的内存重新分配给其他内容,则会出现混乱。


2
即使在两次调用free之间没有重新分配内存,事情通常也会变得混乱。 - Jonathan Leffler

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