不正确的堆释放会中止C程序

时间:2012-01-29 21:13:25

标签: c memory-management malloc free

当尝试释放相同的malloced堆两次或未分配的堆时,分别会出现致命错误“double free或corruption(fasttop)”和“invalid pointer”,因此正在运行的程序会立即中止。

虽然这样做在逻辑上是不恰当的,但在我看来,实际上并没有对正在运行的程序造成致命伤害。为什么它被迫立即中止?

5 个答案:

答案 0 :(得分:3)

立即中止可以最大​​限度地提高您发现错误并修复错误的可能性 这种错误看起来似乎无害,但随着代码的轻微改变,它们是灾难性的,难以调试。

考虑这一点 - 你(A)释放指针p,并在一段时间后再次释放它。同时,一些代码(B)执行malloc,并碰巧得到相同的地址。现在第二个免费似乎没问题,因为p被分配了。现在另一个人(C)做malloc,并再次获得相同的地址(很可能,如果它的大小相同)。当C写入p时,他正在破坏B的数据。谁应该受到责备?答:祝你好运调试。

因此,年轻时应该抓住双倍自由,不能容忍。

答案 1 :(得分:1)

标准中没有任何内容可以保证崩溃。执行双重自由是未定义的行为。它会在某些情况下被运行时库捕获,这样可以通过立即杀死你来免除内存管理错误的进一步伤害。

但你不能依赖它。在你没有注意到的情况下,可能会发生各种形式的沉默,讨厌的堆腐败,并且当发生这种情况时你会吃掉你的数据 - 不好。

运行时尽可能为您提供安全网,但不依赖它。如果你绊倒其中一个,请调试它直到它被真正修复。

答案 2 :(得分:1)

如果你有充分的理由允许双重释放指针等行为,那么我建议你看看使用setjmp和longjmp实现C异常处理,但根据经验,我更倾向于消除这样的逻辑。

答案 3 :(得分:0)

请考虑以下代码:

    int * i = (int *)malloc(2 * sizeof(int));
    free(i);
    int * j = (int *)malloc(sizeof(int));
    int * k = (int *)malloc(sizeof(int));
    free(i);

现在,假设j与[{1}}保持相同的地址,k保留i。当第二个i + 1被命令时,您宣布整个块(free()j)是免费的,而不只是kj实际上知道了多少记忆它必须声明自由)。这种行为可以理解是应该受到谴责的,因为即使您可能已完成free(),您也可以在代码的其余部分使用j

答案 4 :(得分:0)

  

虽然这样做在逻辑上是不恰当的,但在我看来,实际上并没有对正在运行的程序造成致命伤害。

谬误警报。请考虑以下事项:

  • 线程1分配地址42并将'xyzzy'写入其中。
  • 线程1释放地址42。
  • 线程2分配地址42并向其写入“插入”。
  • 线程1错误地再次释放地址42.
  • 线程3分配地址42并将'twisty-little-passages'写入其中。

现在线程2和3 认为他们拥有那个内存。这和我年幼的儿子和女儿都认为他们拥有购买的最新玩具一样可持续,不,它会很好地结束: - )

请记住,这些“线程”暗示不必是多线程环境中的执行线程,这只是我用来显示内存所有权的区别。

错误处理的一个好习惯是:

  • 如果您可以完全修复它,请执行此操作。
  • 如果您无法完全修复,请尽快停止以尽量减少损坏。