小编典典

如何调试堆损坏错误?

all

我正在 Visual Studio 2008 下调试一个(本机)多线程 C++ 应用程序。在看似随机的情况下,我收到“Windows
已触发断点…”错误,并指出这可能是由于堆中的损坏。这些错误不会总是立即使应用程序崩溃,尽管它可能会在不久之后崩溃。

这些错误的最大问题是它们仅在实际发生损坏后才会弹出,这使得它们很难跟踪和调试,尤其是在多线程应用程序上。

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

  • 我该如何调试它们?

欢迎提示、工具、方法、启示……。


阅读 56

收藏
2022-08-21

共1个答案

小编典典

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

Electric
Fence(又名“efence”)、dmallocvalgrind等都值得一提,但其中大多数在
*nix 下比在 Windows 下运行要容易得多。Valgrind 非常灵活:我使用它调试过存在许多堆问题的大型服务器软件。

当所有其他方法都失败时,您可以提供自己的全局运算符 new/delete 和 malloc/calloc/realloc
重载——如何这样做会因编译器和平台而异——这将是一项投资——但从长远来看,它可能会有所回报。dmalloc 和electricfence
以及令人惊讶的优秀书籍中的理想功能列表应该看起来很熟悉:

  • 哨兵值 :在每个分配之前和之后允许更多的空间,尊重最大对齐要求;填充幻数(有助于捕获缓冲区溢出和下溢,以及偶尔的“野生”指针)
  • alloc fill :用一个神奇的非 0 值填充新的分配——Visual C++ 已经在调试版本中为你做这件事(帮助捕获使用未初始化的变量)
  • free fill :用一个神奇的非 0 值填充已释放的内存,旨在在大多数情况下取消引用时触发段错误(有助于捕获悬空指针)
  • 延迟释放 :暂时不要将释放的内存返回到堆中,保持空闲填充但不可用(有助于捕获更多悬空指针,捕获接近的双释放)
  • 跟踪 :能够记录分配的位置有时很有用

请注意,在我们的本地自制系统(对于嵌入式目标)中,我们将跟踪与大多数其他东西分开,因为运行时开销要高得多。


2022-08-21