162 c++ windows debugging heap
我在Visual Studio 2008下调试一个(本机)多线程C++应用程序.在看似随机的场合,我得到一个"Windows触发了一个断点......"错误,并注意到这可能是由于堆.这些错误并不会立即使应用程序崩溃,尽管它很可能会在之后崩溃.
这些错误的一个大问题是它们只在实际发生损坏后弹出,这使得它们很难跟踪和调试,尤其是在多线程应用程序上.
什么样的事情会导致这些错误?
我该如何调试它们?
提示,工具,方法,启发......欢迎.
lea*_*der 126
Application Verifier与Windows调试工具相结合是一个了不起的设置.您可以将它们作为Windows驱动程序工具包或较轻的Windows SDK的一部分.(在研究关于堆损坏问题的早期问题时,发现了关于Application Verifier的问题.)我过去也使用过BoundsChecker和Insure ++(在其他答案中提到过),尽管我对Application Verifier中有多少功能感到惊讶.
电动围栏(又名"efence"),dmalloc,valgrind等等都值得一提,但其中大多数都比*nix更容易在Windows下运行.Valgrind非常灵活:我调试了大型服务器软件,使用它有很多堆问题.
当所有其他方法都失败时,您可以提供自己的全局运算符new/delete和malloc/calloc/realloc重载 - 如何执行此操作会因编译器和平台而有所不同 - 这将是一项投资 - 但从长远来看,它可能会得到回报.理想的功能列表应该看起来很熟悉dmalloc和electricfence,以及令人惊讶的优秀书籍编写固体代码:
请注意,在我们的本地自制软件系统中(对于嵌入式目标),我们将跟踪与大多数其他内容分开,因为运行时开销要高得多.
如果您对更多重载这些分配函数/运算符的理由感兴趣,请查看我的答案"任何理由重载全局运算符new和delete?" ; 除了无耻的自我提升,它列出了有助于跟踪堆损坏错误的其他技术,以及其他适用的工具.
Can*_*pus 35
您可以通过为应用程序启用页面堆来检测大量堆损坏问题.为此,您需要使用gflags.exe作为Windows调试工具的一部分
运行Gflags.exe并在可执行文件的映像文件选项中,选中"启用页面堆"选项.
现在重新启动exe并附加到调试器.启用页堆后,只要发生堆损坏,应用程序就会进入调试器.
小智 12
要真正减慢速度并执行大量运行时检查,请尝试main()在Microsoft Visual Studio C++中添加以下内容或等效项
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_ALWAYS_DF );
Run Code Online (Sandbox Code Playgroud)
什么样的事情会导致这些错误?
用内存做顽皮的事情,例如在缓冲区结束后写入,或者在缓冲区被释放回堆之后写入缓冲区.
我该如何调试它们?
使用一种工具,为您的可执行文件添加自动边界检查:即Unix上的valgrind,或Windows上的BoundsChecker(维基百科也建议使用Purify和Insure ++)等工具.
请注意,这些会降低您的应用程序速度,因此如果您的应用程序是软实时应用程序,它们可能无法使用.
另一种可能的调试辅助工具可能是MicroQuill的HeapAgent.
我从检测对释放内存的访问获得的一个快速提示是:
如果要快速定位错误,而不检查访问内存块的每个语句,可以在释放块后将内存指针设置为无效值:
Run Code Online (Sandbox Code Playgroud)#ifdef _DEBUG // detect the access to freed memory #undef free #define free(p) _free_dbg(p, _NORMAL_BLOCK); *(int*)&p = 0x666; #endif
您使用什么类型的分配函数?我最近使用 Heap* 样式分配函数遇到了类似的错误。
事实证明,我错误地使用该HEAP_NO_SERIALIZE选项创建了堆。这本质上使得堆函数在没有线程安全的情况下运行。如果使用得当,它会提高性能,但如果您在多线程程序中使用 HeapAlloc,则不应使用它 [1]。我之所以提到这一点,是因为您的帖子提到您有一个多线程应用程序。如果您在任何地方使用 HEAP_NO_SERIALIZE,请将其删除,它可能会解决您的问题。
[1] 在某些情况下这是合法的,但它要求您序列化对 Heap* 的调用,并且对于多线程程序通常不是这种情况。
我发现每次都有用和工作的最好的工具是代码审查(有很好的代码审查员).
除了代码审查,我首先尝试Page Heap.页面堆需要几秒钟的时间来设置,运气好的话可能会确定您的问题.
如果页面堆没有运气,请从Microsoft 下载Windows调试工具并学习使用WinDbg.抱歉无法为您提供更具体的帮助,但是多线程堆损坏更多的是艺术而不是科学.谷歌的"WinDbg堆腐败",你应该找到很多关于这个主题的文章.
| 归档时间: |
|
| 查看次数: |
174822 次 |
| 最近记录: |