当试图释放相同的mableced堆两次或未分配的堆时,分别发生致命错误“double free or corruption(fasttop)”和“invalid pointer”,因此运行程序立即中止。不正确释放堆中止C程序
尽管这样做在逻辑上不合适,但在我看来,对于正在运行的程序实际上没有致命的伤害。为什么它被迫立即中止?
当试图释放相同的mableced堆两次或未分配的堆时,分别发生致命错误“double free or corruption(fasttop)”和“invalid pointer”,因此运行程序立即中止。不正确释放堆中止C程序
尽管这样做在逻辑上不合适,但在我看来,对于正在运行的程序实际上没有致命的伤害。为什么它被迫立即中止?
立即中止可最大限度地提高发现错误并修复错误的几率。
这种错误看起来似乎无害,但只需轻微更改代码,它们就是灾难性的,而且很难调试。
考虑一下 - 你(A)释放指针p
,并在一段时间后再次释放它。同时,一些代码(B)做了malloc
,碰巧得到了相同的地址。现在第二个免费版似乎可以,因为分配了p
。现在另一个人(C)做了malloc
,并再次获取相同的地址(很可能,如果它的大小相同)。当C写入p
时,他正在破坏B的数据。谁应该责怪? A.祝你好运调试。
所以双倍免费应该在年轻的时候抓住,不能容忍。
标准中的任何内容都不会保证崩溃。做双免费是未定义的行为。它会在某些情况下被运行时库捕获,这会通过立即杀死你,从而避免进一步损害你的内存管理错误。
但是你不能依赖那个。如果不注意,可能会发生各种形式的沉默,令人讨厌的堆损坏,并且在发生这种情况时您将会吃掉您的数据 - 并不好。
运行时可以为您提供安全网,但不会依赖它。如果你在其中之一上绊倒,调试它直到它被真正修复。
我想从stdlib中寻找is_allocated(堆)... – sof 2012-01-29 21:59:13
如果你有足够的理由允许双重释放一个指针,比我建议你看看使用setjmp和longjmp实现C异常处理,但从经验来看,我更倾向于消除这样的逻辑。
Thx指向'setjmp'和'longjmp'。 – sof 2012-01-29 22:12:31
没有办法允许它。一旦发生双重空闲,你就调用了未定义的行为,整个程序状态是未定义的。 – 2012-01-29 23:59:23
考虑下面的代码:
int * i = (int *)malloc(2 * sizeof(int));
free(i);
int * j = (int *)malloc(sizeof(int));
int * k = (int *)malloc(sizeof(int));
free(i);
现在,假设j
持有相同的地址i
,和K持有i + 1
。当第二个free()
被命令时,你声明整个块(j
,k
)是免费的,而不仅仅是j
(free()
实际上知道它有多少内存要声明免费)。这种行为是可以理解的,因为即使你使用j
,你也可以在代码的其余部分使用k
。
调用'free(heap)'后,我们按照惯例设置'heap = NULL'。再次调用'free(heap)'不会产生这样的副作用。 – sof 2012-01-29 21:45:52
虽然这样做在逻辑上不合适,但在我看来,对于正在运行的程序实际上没有致命的伤害。
谬误警报。考虑以下几点:
现在线程2和3 都认为他们自己的内存。这是我的小儿子和女儿都认为他们拥有那个最新的玩具购买的话,不,这不是有好下场的:-)
记住是关于可持续,那些“线程”提到不必须是多线程环境下的执行线程,这只是我用来显示内存所有权的区别。
一个好的成语对错误处理:
我宁愿用这种方式来默默无视。如果你正在双重释放内存然后显然出了问题,并且很高兴知道它是什么 – Dan 2012-01-29 21:15:58
如果C支持异常处理,我可能更喜欢抛出一个检查的异常,这反过来程序本身需要正确处理。 – sof 2012-01-29 21:22:16
@sof,看着这个问题和你对No的答案的评论,在我看来,当你说“未分配的堆”时,你的意思是一个NULL指针 - 即做相当于free(NULL);或'免费(0);'。是这种情况还是你的意思是'未分配堆'的不同之处? – AAT 2012-01-29 21:54:19