【发布时间】:2011-05-15 10:46:37
【问题描述】:
我最近修复了我们产品中的一个缺陷,其症状是访问悬空指针导致的访问冲突。
为了获得良好的实践,我添加了一个单元测试以确保错误不会再次出现。在编写单元测试时,我总是会退出我的缺陷修复并确保单元测试失败,否则我知道它没有正确地完成它的工作。
退出缺陷修复后,我发现我的单元测试仍然通过(不好)。当我将调试器附加到单元测试以查看其通过的原因时,测试失败(即引发了异常),我可以中断并观察到调用堆栈与我修复的原始缺陷中的堆栈匹配。
我没有修改 Visual Studio 2005 中的“异常中断”设置,这确实是导致测试工具终止的关键 Win32 异常(即没有正常的异常处理程序)。
异常的文字是:
Unhandled exception at 0x0040fc59 in _testcase.exe: 0xC0000005:
Access violation reading location 0xcdcdcdcd.
注意:位置并不总是0xcdcdcdcd (allocated but unwritten Win32 heap memory)。有时是0x00000000,有时是另一个地址。
这似乎与传统的 Heisenbug 相反,通过调试器观察问题时问题就会消失。就我而言,通过调试器观察它会导致问题出现!
我最初的想法是,这是调试器中的时间差异所暴露的竞争条件。但是,当我将跟踪添加到代码并与调试器分开运行时,我打印出来的数据向我表明,应用程序应该以与在调试器下运行时类似的方式中止。但事实并非如此!
关于可能导致此问题的任何建议?
更新:我正在缩小这个问题的原因。有关详细信息,请参阅this question。如果我找到答案,我会用答案更新这个问题。
【问题讨论】:
-
我曾经遇到过这样一个有趣的错误,即在附加调试器时程序崩溃了。我终于发现我有一个线程在调用
sem_wait时被阻塞;调试器在附加时中断了线程,导致sem_wait返回错误EINTR。然后线程继续执行并发生了坏事。可以说,我明白了为什么检查错误代码很重要......
标签: c++ unit-testing debugging debug-build