寻找Heisenbugs的策略

时间:2010-11-01 09:06:26

标签: debugging language-agnostic heisenbug

目前我再一次遇到这样一种情况:我必须找到一个在调试器运行时几乎不会发生的Bug的原因(可能是一些竞争条件)。我能想到的唯一能找到它的是:

  1. 将调试打印和断言添加到代码中,告诉我在没有调试器的情况下发生了什么。
  2. 逐步完成代码并思考每一行以及可能产生的副作用。
  3. 总而言之,这非常令人沮丧。您对这些类型的错误有什么策略和经验?

    编辑:我使用的是Visual C ++ 2005,但我认为这个问题适用于许多(所有)语言和开发环境。

3 个答案:

答案 0 :(得分:4)

如果您可以确定问题首次可见的点(显然不是造成问题的时候),请在那里引发一个例外并使用Process Dumper来获取dump for postmortem debugging。

在IDE外部运行Release二进制文件,然后附加调试器。这样可以避免在调试器内运行的特殊堆和其他标志启用。

如果您知道错误的位置,请将该代码提取到尽可能少的最小化测试应用程序中 - 您正试图将其测试为销毁。同样,只有在代码启动并运行后才附加调试器,以避免许多特定于调试器的副作用。

检查选项 - 使用/W4构建,以确保没有遗漏任何明显的内容。检查C风格的演员表或reinterpret_cast的代码和警告,以防有人抛弃了误解但重要的警告或错误消息。

答案 1 :(得分:2)

我发现在我的C / C ++ / Java代码上运行lint并确保我修复它提供的每个警告都会导致这些竞争条件消失。但这不是解决方案。 绝不巧合。您必须了解您修复的内容以及解决问题的原因。

我认为K(&&amp ;||)R表示丰富的日志消息比任何调试器都更能帮助他们调试代码 - 特别是在多线程环境中,但需要引用。

仔细查看导致错误产生的所有活动的非常详细的痕迹确实有很大帮助。

答案 2 :(得分:1)

当所有技术都结束并且BoundsCheckers或RationalPurify没有帮助时。我通常使用非常愚蠢的技术。我们在大学的第一年就发现了它。在俄语中它被称为非常粗糙。

所以 - 我从选择在多线程环境中失败的可疑块/模块开始。如果不可能,则重新计算程序结构。

当选择模块时,我正在评论小块代码,直到异常消失。这允许定位究竟是什么原因(例如竞争条件)。如果在这一步你可以说出错了 - 那就太好了。

如果没有,同样的技术应用于检测错误的前提条件,所以我正在注释掉预先存在罪魁祸首的代码。