如何调试堆损坏错误?

我在Visual Studio 2008下调试了一个(本机)多线程C ++应用程序。在看似偶然的场合,我得到一个“Windows引发了一个断点...”的错误,并注意到这可能是由于堆。 这些错误不会总是使应用程序崩溃,尽管它很可能会在短期内崩溃。

这些错误的主要问题是,只有在腐败实际发生后才会弹出,这使得他们很难跟踪和调试,特别是在多线程应用程序上。

  • 什么样的事情会导致这些错误?

  • 我如何调试它们?

  • 提示,工具,方法,启示...是受欢迎的。


    应用程序验证程序结合Windows调试工具是一个了不起的设置。 您可以将它们作为Windows Driver Kit或更轻的Windows SDK的一部分。 (在研究关于堆损坏问题的早期问题时,发现了Application Verifier。)我在过去也使用过BoundsChecker和Insure ++(在其他答案中提到过),尽管我很惊讶Application Verifier中有多少功能。

    电篱笆(又名“efence”),dmalloc,valgrind等都值得一提,但其中大多数在* nix下运行比Windows更容易。 Valgrind是非常灵活的:我用大量的堆问题调试了大型服务器软件。

    当所有其他的失败时,你可以提供你自己的全局运算符new / delete和malloc / calloc / realloc重载 - 如何做到这一点将取决于编译器和平台而有所不同 - 这将是一个投资 - 但从长远来看它可能会有所回报。 理想的功能列表看起来应该与dmalloc和电子栏目相似,并且出色的优秀书写固体代码:

  • 哨兵值 :在每次分配之前和之后允许更多空间,尊重最大对齐要求; 用幻数填充(有助于捕捉缓冲区溢出和下溢,偶尔的“狂野”指针)
  • alloc fill :使用非0的魔术值填充新的分配 - Visual C ++已经在Debug版本中为您执行此操作(帮助捕获未初始化的变量)
  • 自由填充 :用魔术非0值填充释放的内存,旨在在大多数情况下解除引用时触发段错误(有助于捕获悬挂指针)
  • 延迟释放 :不会将释放的内存返回堆中一段时间​​,使其自由填充但不可用(有助于捕获更多悬挂指针,捕获接近双释放的内存)
  • 跟踪 :能够记录分配的位置有时可能有用
  • 请注意,在我们的本地自制系统中(对于嵌入式目标),我们将跟踪与大部分其他内容分开,因为运行时开销要高得多。


    如果您有更多理由来重载这些分配函数/操作符,请查看我对“重载全局操作符new和delete”的任何理由的回答。 无耻的自我推销,它列出了其他技术,有助于跟踪堆损坏错误,以及其他适用的工具。


    您可以通过为应用程序启用Page Heap来检测大量堆损坏问题。 为此,您需要使用作为Windows调试工具的一部分的gflags.exe

    运行Gflags.exe并在可执行文件的映像文件选项中,选中“启用页面堆”选项。

    现在重新启动您的exe并附加到调试器。 启用页面堆时,每当发生任何堆损坏时,应用程序都会进入调试器。


    一篇非常相关的文章是使用Application Verifier和Debugdiag调试堆损坏。

    链接地址: http://www.djcxy.com/p/2327.html

    上一篇: How to debug heap corruption errors?

    下一篇: Why does one use dependency injection?