c++ - Win32下堆损坏;如何定位?

标签 c++ windows multithreading debugging memory

我正在处理 多线程 正在破坏堆的 C++ 应用程序。定位此损坏的常用工具似乎不适用。源代码的旧版本(18 个月大)表现出与最新版本相同的行为,所以这已经存在很长时间了,只是没有被注意到;不利的一面是,无法使用源增量来识别引入错误的时间 - 存储库中有很多代码更改。

崩溃行为的提示是在这个系统中产生吞吐量 - 数据的套接字传输被修改为内部表示。我有一组测试数据会定期导致应用程序异常(各种地方,各种原因 - 包括堆分配失败,因此:堆损坏)。

该行为似乎与 CPU 功率或内存带宽有关;每台机器的数量越多,就越容易崩溃。禁用超线程内核或双核内核会降低(但不会消除)损坏率。这表明与时间相关的问题。

现在问题来了:
当它在轻量级调试环境(比如 Visual Studio 98 / AKA MSVC6 )下运行时,堆损坏很容易重现——十到十五分钟后就会发生可怕的失败和异常,比如 alloc;当在复杂的调试环境(Rational Purify、VS2008/MSVC9 甚至 Microsoft Application Verifier)下运行时,系统会受到内存速度限制并且不会崩溃(内存限制:CPU 没有超过 50%,磁盘灯不是上,程序运行得尽可能快,盒子消耗了 1.3G 的 2G RAM)。所以,我可以在能够重现问题(但不能确定原因)或能够确定原因或无法重现的问题之间做出选择。

我目前对下一步的最佳猜测是:

  • 获得一个非常糟糕的盒子(替换当前的开发盒子:E6550 Core2 Duo 中的 2Gb RAM);这将使在强大的调试环境下运行时重现导致错误行为的崩溃成为可能;或
  • 重写运算符 newdelete使用 VirtualAllocVirtualProtect完成后立即将内存标记为只读。在 MSVC6 下运行并让操作系统捕获正在写入释放内存的坏人。是的,这是绝望的迹象:谁他妈的重写newdelete ?!我想知道这是否会使它像 Purify 等人一样慢。

  • 并且,不:内置 Purify 仪器运输不是一种选择。

    一个同事刚走过来问“堆栈溢出?我们现在有堆栈溢出吗?!?”

    现在,问题:如何找到堆损坏程序?

    更新:平衡 new[]delete[]似乎已经在解决问题上走了很长一段路。该应用程序现在在崩溃前大约需要两个小时,而不是 15 分钟。还没有。有什么进一步的建议吗?堆损坏仍然存在。

    更新:Visual Studio 2008 下的发布版本似乎要好得多;目前的怀疑在于 STL VS98 附带的实现.

    1. Reproduce the problem. Dr Watson will produce a dump that might be helpful in further analysis.


    我会记录下来,但我担心 Watson 博士只会在事后被绊倒,而不是在堆被踩踏时。

    Another try might be using WinDebug as a debugging tool which is quite powerful being at the same time also lightweight.



    再次说明这一点:在出现问题之前没有太大帮助。我想在行动中捕获破坏者。

    Maybe these tools will allow you at least to narrow the problem to certain component.



    我不抱太大希望,但绝望的时代需要……

    And are you sure that all the components of the project have correct runtime library settings (C/C++ tab, Code Generation category in VS 6.0 project settings)?



    不,我不是,明天我将花几个小时浏览工作区(其中有 58 个项目)并检查它们是否都在编译并与适当的标志链接。

    更新:这花了 30 秒。选择 Settings 中的所有项目对话框,取消选择,直到找到没有正确设置的项目(它们都有正确的设置)。

    最佳答案

    我的首选是专用的堆工具,例如 pageheap.exe .

    重写 new 和 delete 可能有用,但这并不能捕获低级代码提交的分配。如果这是你想要的,最好绕道low-level alloc API s 使用 Microsoft Detours。

    还有健全性检查,例如:验证您的运行时库是否匹配(发布与调试、多线程与单线程、dll 与静态库)、查找错误删除(例如,delete [] 应该在的地方删除)使用),请确保您没有混合和匹配您的分配。

    还可以尝试有选择地关闭线程并查看问题何时/是否消失。

    第一个异常发生时的调用堆栈等是什么样的?

    关于c++ - Win32下堆损坏;如何定位?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1069/

    相关文章:

    java - 使用udp无连接协议(protocol)在简单的java服务器中可以实现多线程吗?

    c - 读取 FIFO,资源暂时不可用

    c++ - 如何在 `conanfile.txt` 中有条件地指定要求?

    c++ - 用 C 折扣库解析 markdown

    c++ - Qt - QLabel 不会以固定比例调整大小

    C++ Linux 代码破坏了 Windows 构建,因为缺少 header 意味着函数未定义

    c# - 找出当前用户的用户名-当多个用户登录时

    c++ - 为什么临时的生命周期不会延长到封闭对象的生命周期?

    javascript - Firefox 扩展中的 Window less embedded exe

    c++ - 重新排序内存操作的简单示例