如何正确找到海森虫

How to properly find a Heisenbug?

本文关键字:何正确      更新时间:2023-10-16

经过一些资源修改(图像(,我的程序一直随机崩溃(0xC0000005(。我知道这些来自糟糕的内存管理,但我找不到它的来源,原因有两个:首先,我没有手动使用很多指针或动态分配的变量(我的意思是我使用为我做的标准库(,其次,当我使用 gdb 调试时不会发生错误(但它确实在运行调试版本时出现, 没有GDB(。

我试图用sd::cout查明错误,但由于我的程序编写方式,我仍然找不到它。我仔细检查了我使用的指针和动态数组,但仍然找不到它。有关信息,debug 是使用 "-g -std=c++14" 编译的,但没有"-O2"。我将Code::Block与 GCC 5.1.0 和 gdb 7.9 的 64 位 MingW 一起使用。

所以,我读了很多关于这类bug(0xC0000005(和Heisenbug的东西,但我不知道如何处理它,我不知道现在该尝试什么。

我会给你看代码,但它分布在 30 个文件中。如果你真的想看,它在github上。

此外,您将无法对其进行测试,因为我没有上传资源文件(我不拥有它们(。

那么,您有什么建议让我能够找到错误的来源吗?

启动程序,然后附加gdb ;如果在调试器下启动程序,Windows 将切换到调试堆,这通常可以帮助检测内存使用问题,但有时会隐藏 Heisenbug(因为它实际上会更改未初始化内存的默认内容(。

通过启动程序,然后附加调试器,可以避免"正常"运行和"调试"运行之间的这种差异,因此您应该能够直接在调试器中捕获访问冲突。

除了"设法在调试器下重现崩溃"之外,您可能还希望使用各种可以帮助您更早地检测错误的工具;最近的 g++ 版本提供了地址清理器和调试 STL 等工具,这有助于我查明许多多年来未解决的严重错误。

顺便说一句,即使程序尚未在调试器下,Windows也提供了在崩溃的情况下启动其中一个注册程序的可能性,在通常的崩溃对话框中应该有一个"调试"选项。似乎不可能在系统调试器之间注册gdb,但是如果您安装了Visual C++ Express或Windows调试工具,则至少应该始终为这些场合准备好某种调试器(使用它们来调试g++生成的可执行文件,其中包含矮小的调试信息而不是PDB是另一罐蠕虫, 虽然(。

通常,当程序实际崩溃时,对于有用的内存转储来说为时已晚。数据损坏可能很久以前就发生了。

我会使用 valgrind 来尽早检测无效的内存访问。这不会发现所有类型的数据损坏,但至少不会发现与非法读取和写入(缓冲区溢出、未初始化读取等(相关的几乎所有内容。

这已经对"海森虫"有很大帮助