3

为了追踪内存泄漏,我一直在使用 Visual Studio 和 SOS.dll 来提供对象堆的转储,并查看 GCRooting 特定对象的位置。

我开始使用 AutoIt 自动化这个过程来控制我的鼠标和键盘。这是我的脚本第一部分的近似值:

在 Visual Studio 中按 F5 开始执行
让程序完全加载
切换到 Visual Studio 并中断执行

将焦点切换到即时窗口
Load SOS.dll
Call!dumpheap -stat
将转储结果复制到剪贴板
粘贴到记事本中并另存为 dump1.txt

继续执行
多次执行泄漏操作
切换到 Visual Studio 并中断执行

将焦点切换到即时窗口
清除输出
Call!dumpheap -stat
将转储结果复制到剪贴板
粘贴到记事本并另存为 dump2.txt

运行一个 Python 脚本,比较两个转储并定位泄漏的对象

不过,我对我目前的方法有一些担忧。我不仅依赖于 Visual Studio 的安装,而且在脚本运行时,我无法使用鼠标或键盘而不会使自动化顺序混乱。

有没有办法在 C# 程序而不是 Visual Studio 中使用 SOS.dll?理想情况下,此解决方案将附加到指定进程并将结果输出!dumpheap -stat到文本文件,而无需自动化 Visual Studio。

4

1 回答 1

9

下面我将介绍一些您可以用来查找泄漏的不同方法。

(如果您不希望遵循 DIY 方法,可以使用商业“泄漏”检测器)。

链接到我的答案,详细说明了许多调试工具/资源

将 SOS.DLL 加载到 WinDBG

您实际上不需要 Visual Studio 来使用 SOS.DLL ....它是一个调试器扩展,因此也可以在 WinDBG 中使用。

作为 Windows 调试工具的一部分,您可以免费获得 WinDBG 调试器。

然后,您可以编写一个 WinDBG 脚本来自动化您的“转储”。

另请注意,有可用的 SOS.DLL 增强版本...查找 SOSEX、PSSCOR2(用于 NET 2)和 PSSCOR4(用于 NET 4)。

CLR 分析 API

您可以使用 CLR 分析 API。

有一个名为 CLRProfiler 的应用程序,它是一个使用它的实际 .NET 分析器......所以有很多代码来看看它是如何使用的。

CLR Profiler 可以做的一件事是允许进行堆转储,然后比较在不同时间段进行的转储,以找出差异……从而帮助发现泄漏。

您可以在“测试”模式下为您的应用程序提供类似的功能(嵌入在应用程序中,或作为监控它的配套实用程序)。

进程转储

您可以使用的另一种技术是定期“转储”您的进程,然后您可以通过带有 SOS/SOSEX(或任何其他 WinDBG 插件)的 WinDBG 对其进行离线分析。

您可以使用 DebugDiag(您可以设置规则和操作来控制何时创建 .dmp 文件)来自动创建 .dmp 文件......或名为 ProcDump.exe 的工具(来自 SysInternals)。

ProcDump 特别有用,因为它能够非常快速地获取“进程快照”,因为它使用了一种称为“进程反射”的技术......

(创建 3 个转储,每个转储之间间隔 5 秒)

procdump -s 5 -n 3 notepad.exe notepad.dmp 

验尸分析

拥有一组 .dmp 文件后,您可以分析它们以查找泄漏、监控句柄使用情况等。

您可以在 WinDBG 中手动加载 .dmp 文件,然后发出调试器命令,或者您可以编写一个 WinDBG 扩展或一个脚本来获取转储文件集并依次处理它们(即在它们上运行 !dumpheap stat 命令) .

调试分析器 .NET

这是一个旨在分析 .dmp 文件并进行事后分析的工具。

它允许您在 .NET 中编写脚本,因此可能比 WinDBG 更易于访问。

如果你想扩展它,它也有一个插件模型。

它允许您编写/使用可视化工具以独特的方式查看数据。

(目前仅支持 CLR 2.0 内存转储...不支持 CLR 4.0)

于 2012-08-31T21:52:52.823 回答