Jos*_*osh 59 c++ memory windows debugging multithreading
我正在研究破坏堆的多线程 C++应用程序.找到这种腐败的常用工具似乎不适用.源代码的旧版本(18个月之前)表现出与最新版本相同的行为,因此这已经存在了很长时间并且没有被注意到; 在缺点方面,源增量不能用于识别何时引入错误 - 存储库中存在大量代码更改.
崩溃行为的提示是在这个系统中产生吞吐量 - 数据的套接字传输,它被导入内部表示.我有一组测试数据会定期导致应用程序异常(各种地方,各种原因 - 包括堆分配失败,因此:堆损坏).
行为似乎与CPU功率或内存带宽有关; 机器越多,崩溃就越容易.禁用超线程核心或双核核心可降低(但不消除)损坏的速度.这表明与时间相关的问题.
现在这里有一个问题:
当它在一个轻量级的调试环境下运行时(比方说Visual Studio 98 / AKA MSVC6),堆损坏相当容易重现 - 在事情失败和异常失败之前经过十或十五分钟,就像alloc;在复杂的调试环境下运行时一样(Rational Purify,VS2008/MSVC9或者甚至是微软应用程序验证程序)系统变得内存速度受限并且不会崩溃(内存限制:CPU没有达到上面50%,磁盘指示灯不亮,程序运行速度快,盒子消耗1.3G2G RAM) .因此,我可以选择能够重现问题(但不能确定原因)或能够识别原因或我无法重现的问题.
我目前最好的猜测是下一步是:
E6550 Core2 Duo); 这样可以在强大的调试环境下运行时重现崩溃导致错误行为; 要么new并delete使用VirtualAlloc并VirtualProtect在完成后将内存标记为只读.运行MSVC6并让操作系统捕获正在写入释放内存的坏人.是的,这是绝望的标志:谁是地狱重写new和delete?!我想知道这是否会使它像Purify等人一样慢.而且,不是:内置Purify仪器的运输不是一种选择.
一位同事刚刚走过去问"Stack Overflow?我们现在收到堆栈溢出了吗?!?"
现在,问题是:我如何找到堆腐败者?
更新:平衡new[],delete[]似乎已经有很长的路要走解决问题.而不是15分钟,应用程序现在大约两个小时崩溃.还没有.还有什么建议?堆损坏仍然存在.
更新:Visual Studio 2008下的发布版本似乎要好得多; 目前的怀疑依赖于STL随船携带的实施VS98.
- 重现问题.
Dr Watson将生成一个可能有助于进一步分析的转储.
我会注意到这一点,但我担心沃森博士只会在事后被绊倒,而不是当堆被踩到时.
另一个尝试可能是使用
WinDebug作为调试工具,它同时也很轻巧,非常强大.
此刻再次发生这种情况:在出现问题之前没有多大帮助.我想抓住这个行为中的破坏者.
也许这些工具可以让您至少将问题缩小到某个组件.
我不抱太大希望,但绝望的时候要求......
并且您确定项目的所有组件都具有正确的运行时库设置(
C/C++ tabVS 6.0项目设置中的代码生成类别)吗?
不,我不是,明天我将花费几个小时浏览工作区(其中有58个项目)并检查它们是否正在编译并链接相应的标志.
Settings对话框中的所有项目,取消选择,直到找到没有正确设置的项目(它们都具有正确的设置).
小智 28
我的第一选择是一个专用的堆工具,如pageheap.exe.
重写new和delete可能很有用,但是它不会捕获较低级代码提交的alloc.如果这是你想要的,最好low-level alloc API使用Microsoft Detours绕道而行.
还要进行健全性检查,例如:验证运行时库是否匹配(发布与调试,多线程与单线程,dll与静态库),查找错误删除(例如,删除删除[]应该是使用过),确保你没有混合和匹配你的分配.
还可以尝试选择性地关闭线程并查看问题何时消失.
在第一个异常时调用堆栈等是什么样的?
Mic*_*der 11
我的工作也有同样的问题(VC6有时我们也会使用).并没有简单的解决方案.我只有一些提示:
STLtry STLPort和checked版本.无效的迭代器是地狱.祝好运.像你这样的问题花了我们几个月来解决.为此做好准备......
运行原始应用程序ADplus -crash -pn appnename.exe
当弹出内存问题时,您将获得一个很好的大转储.
您可以分析转储以确定哪个内存位置已损坏.如果幸运的话,覆盖内存是一个唯一的字符串,你可以弄清楚它来自哪里.如果你不幸运,你将需要挖掘win32堆并计算出原始记忆特征是什么.(堆-x可能有帮助)
在您知道什么是混乱后,您可以使用特殊堆设置缩小appverifier使用率.即,您可以指定DLL要监视的内容或要监视的分配大小.
希望这将加速监控,足以抓住罪魁祸首.
根据我的经验,我从不需要完整的堆验证模式,但我花了很多时间分析崩溃转储和浏览源.
PS:
您可以使用DebugDiag来分析转储.它可以指出DLL拥有损坏的堆,并为您提供其他有用的细节.
通过编写我们自己的malloc和免费函数,我们运气良好.在生产中,他们只是调用标准的malloc并且是免费的,但在调试中,他们可以做任何你想做的事情.我们还有一个简单的基类,除了覆盖new和delete操作符以使用这些函数之外什么都不做,然后你编写的任何类都可以简单地从该类继承.如果你有大量的代码,那么替换对malloc的调用并免费使用新的malloc并且免费(不要忘记realloc!)可能是一个很大的工作,但从长远来看它非常有用.
在Steve Maguire的书"强化建议书"(强烈推荐)中,您可以在这些例程中进行调试,例如:
另一个好主意是从来没有使用之类的东西strcpy,strcat或者sprintf-始终使用strncpy,strncat和snprintf.我们也编写了我们自己的这些版本,以确保我们不会写下缓冲区的末尾,这些也遇到了很多问题.
| 归档时间: |
|
| 查看次数: |
35205 次 |
| 最近记录: |