我正在开发一个破坏堆的多线程C++ 应用程序。定位这种损坏的常用工具似乎不适用。源代码的旧版本(18 个月大)表现出与最新版本相同的行为,所以这已经存在很长时间了,只是没有被注意到;不利的一面是,源增量不能用于识别何时引入错误 -存储库中有很多代码更改。
崩溃行为的提示是在该系统中生成吞吐量 - 数据的套接字传输,该数据被转换为内部表示。我有一组测试数据会定期导致应用程序异常(各种地方,各种原因 - 包括堆分配失败,因此:堆损坏)。
该行为似乎与 CPU 功率或内存带宽有关;每台机器拥有的越多,就越容易崩溃。禁用超线程内核或双核内核会降低(但不会消除)损坏率。这暗示了一个与时间相关的问题。
现在问题来了:
当它在轻量级调试环境(比如Visual Studio 98 / AKA MSVC6
)下运行时,堆损坏相当容易重现 - 十到十五分钟后,某些事情会发生可怕的失败和异常,例如alloc;
在复杂的调试环境下运行时(Rational Purify,VS2008/MSVC9
甚至微软应用程序验证程序)系统成为内存速度限制并且不会崩溃(内存限制:CPU没有超过50%
,磁盘灯不亮,程序运行速度尽可能快,消耗1.3G
2G RAM的盒子) . 因此,我可以在能够重现问题(但不能识别原因)或能够识别原因或我无法重现的问题之间做出选择。
我目前对下一步的最佳猜测是:
- 获得一个疯狂的盒子(替换当前的开发盒:2Gb RAM in an
E6550 Core2 Duo
);这将使在强大的调试环境下运行时重现导致错误行为的崩溃成为可能;或者 - 重写操作符
new
,并delete
在完成后立即使用VirtualAlloc
并将VirtualProtect
内存标记为只读。运行MSVC6
并让操作系统捕获正在写入释放内存的坏人。是的,这是绝望的迹象:到底是谁重写new
和delete
?!我想知道这是否会使它像 Purify 等人一样慢。
而且,不:不能选择内置 Purify 仪器。
一位同事刚刚走过,问“堆栈溢出?我们现在堆栈溢出了吗?!?”
现在,问题是:我如何找到堆损坏器?
更新:平衡new[]
,delete[]
似乎在解决问题方面取得了长足的进步。现在,该应用程序在崩溃前大约需要两个小时,而不是 15 分钟。还没有。有什么进一步的建议吗?堆损坏仍然存在。
更新:Visual Studio 2008 下的发布版本似乎要好得多;STL
目前的怀疑取决于VS98
.
- 重现问题。
Dr Watson
将产生一个可能有助于进一步分析的转储。
我会记下这一点,但我担心 Watson 博士只会在事后被绊倒,而不是在堆被踩踏时。
另一种尝试可能是
WinDebug
用作调试工具,它非常强大,同时也是轻量级的。
现在又开始了:在出现问题之前没有太多帮助。我想在行为中抓住破坏者。
也许这些工具至少可以让您将问题缩小到某个组件。
我不抱太大希望,但绝望的时候需要...
您确定项目的所有组件都具有正确的运行时库设置(
C/C++ tab
VS 6.0 项目设置中的代码生成类别)吗?
不,我不是,明天我将花几个小时浏览工作区(其中有 58 个项目)并检查它们是否都在编译并与适当的标志链接。
更新:这需要 30 秒。选择对话框中的所有项目
Settings
,取消选择,直到找到没有正确设置的项目(它们都有正确的设置)。