我最近修复了我们产品中的一个缺陷,其症状是由于访问悬空指针而导致访问冲突。
为了获得良好的实践,我添加了一个单元测试以确保错误不会再次出现。在编写单元测试时,我总是会取消缺陷修复并确保单元测试失败,否则我知道它没有正确完成其工作。
在取消缺陷修复后,我发现我的单元测试仍然通过(不好)。当我将调试器附加到单元测试以查看其通过的原因时,测试失败了(即引发了异常),并且我可以中断并观察到调用堆栈与我修复的原始缺陷中的调用堆栈相匹配。
我没有修改 Visual Studio 2005 中的“异常中断”设置,这确实是一个关键的 Win32 异常,它会导致测试工具终止(即没有优雅的异常处理程序)。
异常的文本是:
Unhandled exception at 0x0040fc59 in _testcase.exe: 0xC0000005:
Access violation reading location 0xcdcdcdcd.
Note:位置并不总是0xcdcdcdcd
(已分配但未写入的 Win32 堆内存)。有时是0x00000000
,有时是另一个地址。
这似乎与传统的 Heisenbug 正好相反,当通过调试器观察问题时,问题就会消失。就我而言,通过调试器观察它会使问题出现!
我最初的想法是,这是调试器中的时序差异所暴露的竞争条件。但是,当我向代码添加跟踪并与调试器分开运行时,我打印出的数据向我表明应用程序应该以与在调试器下运行时类似的方式中止。但事实并非如此!
关于可能导致这种情况的原因有什么建议吗?
Update:我正在缩小这个问题的原因。看这个问题更多细节。如果我找到答案,将用答案更新这个问题。
通常,当您删除指向该内存的指针时,VC++ 调试器将用一些已知值填充堆分配的内存。我已经有一段时间没有使用 Visual Studio 了,但对我来说 0xcdcdcdcd 可能是这样一个值似乎是合理的。在我看来,应用程序在调试器中运行时很可能会正常崩溃。当在发布模式下运行时,运行时不会浪费时间覆盖已释放的内存,因此有时您会“幸运”并且存储在该内存中的数据仍然有效。
您可以修改构建设置,以打开在发布模式下用已知值填充已释放内存的选项(完成后不要忘记再次将其关闭)。我猜如果你这样做,你的应用程序会在发布模式下崩溃。
我知道该值并不总是 0xcdcdcdcd,这可能意味着我错了,或者可能意味着您有多个指向悬空指针的路径。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)