我正在 Visual Studio 2008 下调试(本机)多线程 C++ 应用程序。在看似随机的情况下,我收到“Windows 已触发断点…”错误,并指出这可能是由于堆。这些错误不会总是立即使应用程序崩溃,尽管它可能会在不久之后崩溃。
这些错误的最大问题是它们仅在实际发生损坏后才会弹出,这使得它们很难跟踪和调试,尤其是在多线程应用程序上。
什么样的事情会导致这些错误?
我该如何调试它们?
欢迎使用提示、工具、方法、启示……。
原文由 Beef 发布,翻译遵循 CC BY-SA 4.0 许可协议
应用程序验证器 与 Windows 调试工具 相结合是一个了不起的设置。您可以将两者作为 Windows Driver Kit 的一部分或较轻的 Windows SDK 获得。 (在研究 有关堆损坏问题的早期问题 时发现了 Application Verifier。)我过去也使用过 BoundsChecker 和 Insure++(在其他答案中提到),尽管我很惊讶 Application Verifier 中有多少功能。
Electric Fence(又名“efence”)、 dmalloc 、 valgrind 等都值得一提,但其中大多数在 *nix 下比在 Windows 下运行要容易得多。 Valgrind 非常灵活:我使用它调试过存在许多堆问题的大型服务器软件。
当所有其他方法都失败时,您可以提供自己的全局运算符 new/delete 和 malloc/calloc/realloc 重载——如何这样做会因编译器和平台而异——这将是一项投资——但从长远来看,它可能会有所回报。 dmalloc 和electricfence 以及令人惊讶的优秀书籍 Writing Solid Code 中的理想功能列表应该看起来很熟悉:
请注意,在我们的本地自制系统(对于嵌入式目标)中,我们将跟踪与大多数其他内容分开,因为运行时开销要高得多。
如果您对重载这些分配函数/运算符的更多原因感兴趣,请查看 我对“任何理由重载全局运算符 new 和 delete?”的回答。 ;除了无耻的自我推销之外,它还列出了有助于跟踪堆损坏错误的其他技术,以及其他适用的工具。
因为在搜索 MS 使用的 alloc/free/fence 值时,我一直在这里找到自己的答案,所以这是 另一个涵盖 Microsoft dbgheap fill values 的答案。