在堆损坏的情况下新的抛出?

时间:2011-07-06 07:17:20

标签: c++ heap-corruption

如果堆损坏,可以new抛出吗?

如果我理解正确,在堆损坏的情况下,所有赌注都会关闭,任何事情都可能发生。这是对的吗?

4 个答案:

答案 0 :(得分:8)

是的,如果堆已损坏,任何事情都可能发生。抛出异常是可能的,但不太可能。更有可能的是,它会开始摧毁记忆;如果你幸运,你只会得到一个GPF / Segmentation故障。如果你运气不好,你的程序将继续以损坏的堆运行。

答案 1 :(得分:6)

(从评论转移到Als建议的答案,并延伸到更好或更差:-))

损坏的堆会使您对程序的任何行为期望无效。至关重要的是,抛出异常意味着一些可靠的程序化处理是可能的,但没有实现检测堆损坏可能知道这是否真实,因此它们更可能assert或类似

如果我们考虑堆可能具有哪些类型的损坏:

  • 与堆的当前状态相关的损坏记录。

    • 分配和/或免费列表。损坏可能意味着以后的堆分配取消引用无效指针,堆的某些部分被批发泄漏,以后在new / new[] / delete / {期间调用的堆分配或解除分配算法{1}} / delete[] / malloc / realloc无限循环等等。
    • 同步对象。堆例程的实现所使用的互斥锁,条件变量等的状态可能已损坏,导致死锁,竞争条件,以及相关函数调用期间的后续失败。
    • 计数器记录由free构造的数组元素的数量:腐败意味着delete []将破坏错误数量的元素。如果数量减少,一些对象将不会被破坏,可能导致它们包含指针的内存泄漏,未能减少参考计数器,文件句柄保持打开,互斥锁保持锁定,共享内存段未被破坏等。如果数量增加,new[]可能访问包含数组的内存 - 可能导致SIGSEGV - 调用与内存内容delete[]相当的析构函数作为要销毁的对象。这可能会尝试取消引用/删除/释放无效指针,关闭“随机”文件句柄等。
  • 申请数据

    • 应用程序本身通过reintrepet_cast<>new创建的对象可能已损坏,破坏程序状态,指针和包含它们的句柄等。问题可能以多种方式表现出来。

更一般地说关于堆,最好你可以希望新的将在堆耗尽时抛出,但即使这远远没有保证 - 特别是在只有new[]分配虚拟内存的操作系统上,以及如果以后不能满足页面错误,它们表现为SIGSEGV或类似的。

答案 2 :(得分:5)

堆损坏是一种未定义的行为。 new throw可能不是{{1}}。内存分配器最终是一个代码,它读取堆内存并分配内存或提示没有可用的内存。现在,如果阅读窗格已损坏,那么事情就会变得疯狂!

答案 3 :(得分:3)

new依赖于某些内存分配器,具体取决于实现。它可以是malloc,HeapAlloc(例如),或者您在碰巧使用的操作符上定义的任何内容。所以问题实际上是new使用的分配器在其数据结构被破坏时的行为方式。当然,这取决于实现。