从故障转储中查找 GDI/用户资源使用情况

Posted

技术标签:

【中文标题】从故障转储中查找 GDI/用户资源使用情况【英文标题】:Finding GDI/User resource usage from a crash dump 【发布时间】:2010-09-11 08:57:10 【问题描述】:

我有一个应用程序的故障转储,据说该应用程序正在泄漏 GDI。该应用程序在 XP 上运行,我可以毫无问题地将其加载到 WinDbg 中查看它。以前我们使用Gdikdx.dll extension 来查看 Gdi 信息,但 XP 或 Vista 不支持此扩展。

有没有人有任何指针可以在 WinDbg 中查找 GDI 对象的使用情况。

另外,我确实可以访问失败的程序(及其压力测试套件),因此如果您知道任何用于 XP 和 Vista(或 Windows 2000 的“实时”调试工具,尽管这不是我们的目标)。

【问题讨论】:

【参考方案1】:

上周我一直在研究 GDI 泄漏查找工具。我们还执行定期压力测试,并且由于用户/gdi 对象句柄过度消耗,它的持续时间永远不会超过一天的价值。

据我所知,我的尝试非常成功。当然,我事先花了一些时间寻找另一种更快的解决方案。值得一提的是,我之前在上面提到的 msdn 文章中对 GDILeaks 工具有过一些半幸运的经验。更不用说在投入使用之前我必须解决一些问题,而这一次它只是没有给我想要的东西和方式。他们方法的缺点是重量级的调试器接口(它使研究目标减慢了几个数量级,我认为这是不可接受的)。另一个缺点是它并非一直有效 - 在某些运行中,我根本无法让它报告/计算任何东西!它的复杂性(从代码量来看)是另一个吓人的因素。我不是 GUI 的忠实拥护者,因为我相信在没有窗口的情况下我的工作效率更高;o)。我还发现很难让它找到并使用我的符号。

在开始编写自己的工具之前,我使用的另一个工具是leakbrowser。

无论如何,我最终选择了一种迭代方法来实现以下目标:

轻微的性能损失 实现简单 非侵入性(用于多种产品) 尽可能多地依赖可用资源

我使用 detours(非商业用途)来实现核心功能(它是一个可注入的 DLL)。将 javascript 用于自动代码生成(15K 脚本生成 100K 源代码 - 我无法手动编写代码,也不涉及 C 预处理器!)加上用于数据分析和快照/差异支持的 windbg 扩展。

长话短说 - 在我完成之后,在另一个压力测试期间收集信息只需要几个小时,而分析和修复漏洞则需要另外一个小时。

我非常乐意分享我的发现。

附:我花了一些时间来尝试改进以前的工作。我的意图是尽量减少误报(我在开发过程中看到的误报太多了),因此它还将检查分配/释放的一致性,并避免考虑从未泄露的分配。

编辑:找到工具here

【讨论】:

【参考方案2】:

有一个MSDN Magazine article from several years ago 谈到了 GDI 泄漏。这指出了几个不同的地方有很好的信息。

在 WinDbg 中,您也可以尝试使用 !poolused 命令获取一些信息。

从故障转储(事后分析)中查找资源泄漏可能很困难——如果它总是在同一个地方,使用泄漏内存的同一个变量,而且你很幸运,你可以看到最后一个地方它会被泄露,等等。在调试器下运行实时程序可能会容易得多。

您也可以尝试使用Microsoft Detours,但许可证并不总是有效。它也更具侵入性和先进性。

【讨论】:

【参考方案3】:

我为此创建了一个 Windbg 脚本。看看

的回答

Command to get GDI handle count from a crash dump

要跟踪分配堆栈,您可以在最后分配的 GDICell 对象之后设置一个 ba(访问中断)断点,以便在另一个 GDI 分配发生时中断。这可能有点复杂,因为地址发生了变化,但它足以找到几乎任何泄漏。

【讨论】:

以上是关于从故障转储中查找 GDI/用户资源使用情况的主要内容,如果未能解决你的问题,请参考以下文章

在崩溃转储中查找所有可能的上下文记录

在崩溃转储中查找所有可能的上下文记录

将自定义数据包含到 iOS 故障转储中

如何从启用优化(发布模式)构建的二进制文件中分析故障转储?

在大型 Java 堆转储中查找内存泄漏的方法

如何获取 erlang 故障转储文件?