如何创建、使用和调试 .NET 应用程序崩溃转储
转自:https://michaelscodingspot.com/how-to-create-use-and-debug-net-application-crash-dumps-in-2019/?_x_tr_sl&_x_tr_tl&_x_tr_hl
.NET 故障排除中最有用的工具之一是转储文件。这可能是调试崩溃和生产调试的最佳工具。
在本文中,我们将了解转储文件究竟是什么、它们为何如此有用以及如何正确使用它们。您将看到创建转储文件的所有方法,将它们与符号和源文件正确匹配,以及最终如何调试它们以解决问题。
虽然转储可用于本机程序和托管程序,但本文仅指托管 .NET 程序。
目录:
.NET 中的转储文件是什么?
内存转储文件(.dmp文件)是给定时间(例如崩溃期间)程序内存的快照。使用转储文件,您可以查看当前执行的代码行、本地值的值和所有堆对象的值。换句话说,转储文件表示程序在捕获时的整个状态。
转储通常用于调试崩溃(Crash Dumps),但也有其他用途。从最常见到最少,它们是:
转储类型
有 2 种转储文件类型:Full Memory Dump和Minidump。完整内存转储包含程序的整个内存。它可以变得非常大。
小型转储具有误导性名称。它是一种可配置的转储格式。它可以包含整个内存,占用与完整内存转储一样多的空间(甚至更多),或者它可以只包含每个配置的部分内存。(来源)
对于 .NET,我们将主要使用带有整个内存的 Dumps 以获得完整的调试体验。它可以是完整内存转储或配置为包含整个内存空间的小型转储。
如何创建/捕获转储
有很多方法可以创建转储。我将展示一些更常见和推荐的:
1.调试时使用Visual Studio
调试时,转到调试 | Save Dump As...
这将使用 Heap保存小型转储,其中包括完整的内存空间。
2. 使用任务管理器
打开任务管理器,转到详细信息,右键单击所需进程并选择创建转储文件。

这将创建一个完整的内存转储。
3. 使用 ProcDump
ProcDump是 SysInternal 工具包,这是一套非常有用的 Windows 开发工具。ProcDump 本身是一个用于创建转储的命令行工具。它可以按需生成转储或通过监视程序并在崩溃或挂起时创建转储。这是我捕获转储的首选工具。
立即创建具有完整内存的转储的简单用例是:
|
1
2
|
procdump
-
ma
[
process
ID
]
procdump
-
ma
[
name
of
executable
,
for
example
"notepad"
]
|
这会在您的工作目录中创建一个名为:[process name]_[date]_[time].dmp 的转储文件。
您可以监控内存使用情况、挂起的程序、CPU 使用情况、第一次机会异常等情况,并根据需要创建转储。例如,当myprogram.exe挂到名为的文件时,这会捕获转储 转储文件 .dmp。
|
1
|
procdump
-
h
myprogram
.
exe
dumpfile
.
dmp
|
所有功能的信息都在这里。
4. 使用进程浏览器
Process Explorer是SysInternal工具包中的另一个工具。您可以找到哪些进程加载了某个 DLL 或句柄,当然可以查看活动线程、注册表项和创建转储。
右键单击任何进程并选择 Create Dump | Create Full Dump…

5. 崩溃时自动创建转储
您可以让 Windows 在程序崩溃时自动生成转储文件。这是通过 Windows 错误报告 (WER) 完成的。您可以在注册表中进行配置:
- 运行 regedit.exe
- 打开或创建密钥HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps
- 添加与您的程序同名的键 . 例如,Snagit32.exe。
- 添加键:
1. DumpFolder (REG_EXPAND_SZ) – 应在其中创建转储的文件夹
2. DumpCount (REG_DWORD) – 在覆盖旧转储之前创建的最大转储数量。默认值为 10。
3. DumpType (REG_DWORD) – Minidump (1) 或 Full dump (2)。对于.NET应用使用Full dump (2)。
注册表应如下所示:

调试转储
创建转储是简单的部分。真正的挑战是调试它们并理解问题。
有几种方法可以调试转储文件:
1. 使用 Visual Studio
可能最简单的方法是在 Visual Studio 中打开转储文件 (.dmp)。假设您可以匹配符号(.pdb 文件)和源文件,您将获得完整的调试体验。也就是说,您会看到代码就像站在断点上一样。如果它是Crash Dump,那么您将看到导致崩溃的异常。您还应该看到线程、调用堆栈、局部变量、加载的模块等。
使用 Visual Studio 进行调试的说明:
- 在 Visual Studio 中打开 .dmp 文件
- 点击“Debug with Managed Only”或“Debug with Mixed”

3.等待VS尝试加载符号并匹配到源代码。
4. 如果加载了符号,您将看到代码。否则,您应该看到调用堆栈、异常信息(如果在异常时捕获)以及可能的本地值。
5. 像在常规 Visual Studio 调试中一样调查异常或问题。

将符号和源代码文件与 Visual Studio 中的转储匹配
在最后的图片中您可以看到没有加载符号的转储是什么样子。可以看到里面的调用栈、本地值、异常信息、线程和加载的模块。通常,这足以找到问题。
通过加载符号文件,您还可以直接在 Visual Studio 中查看代码。为此,您将需要.pdb 文件和实际的源文件。默认情况下,在每次构建后,符号(.pdb 文件)与程序集(.exe 和 .dll 文件)一起在bin\Debug或bin\Release目录中创建。建议使用包含的符号部署您的程序/NuGet。
重要的是要了解符号和源代码应该与创建转储时的版本完全匹配。否则,匹配将失败。
Visual Studio 尝试自行查找符号文件。它看起来在:
- 可执行文件所在的目录(您的bin\debug或bin\release)
- 打开的.dmp文件的目录
- 符号目录,可以在 Tools | Debugging | Symbols。
- 符号服务器
因此,要加载符号,您只需将它们放在上述目录之一中。您还可以从 Visual Studio(如从模块窗口)手动加载单个符号。
如果您有程序集(.exe 和 .dll),那么您可以反编译它们以获得源代码并提取它们的符号。像dotPeek这样的程序可以提取符号 + 源代码并充当符号服务器。然后,您可以在 Visual Studio 的工具中添加该符号服务器。
有两种技术可以自动从 .pdb 文件中获取源代码:Source Server和较新的Source Link。我从来没有使用过它们,但我相信Source Link嵌入了一个链接到正确的git commit和相关的源代码版本。
2. 使用 WinDbg 调查转储
WinDbg被认为是调查转储文件的首选工具。现在,我不建议在简单的情况下使用它,在这种情况下,您可以在 Visual Studio 中打开转储并在图形 IDE 中获取相同的信息。
话虽如此,Visuals Studio 在能力方面仍在追赶。WinDbg 可以探索对象堆、提取模块、发现死锁以及做很多 VS 仍然做不到的事情。
如果您不熟悉 WinDbg,它是一个(主要)Windows 命令行调试工具。WinDbg 可用于本机程序或带有SOS 调试扩展的托管 .NET 程序 。
开始使用 WinDbg:
- 使用Windows 调试工具安装 WinDbg 。
- 打开正确的 WinDbg 版本——有 x86 和 x64 windbg.exe可执行文件,它们应该与 Dump 的位数匹配。查看以下文件夹:
C:\Program Files (x86)\Windows Kits\10\Debuggers\x64
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86 - 在 WinDbg 中,打开您保存的转储 (Ctrl + D)
- 开启详细日志
!sym noisy - 设置符号搜索路径
.sympath srv*https://msdl.microsoft.com/download/symbols
.sympath+ cache*C:\debug\symbols
.sympath+ C:\MyApp\bin\Debug - 强制重新加载符号
.reload
ld* - 加载 SOS 扩展
.loadby sos clr - 继续执行其他命令
如指令#5 所示,您可以从任何目录或符号服务器加载符号(如果有的话)。在这方面,它类似于 Visual Studio。
那么你可以用 WinDbg 做什么呢?
无论您可以使用Visual Studio做什么,您也可以使用WinDbg等等。这里有一些你可以用WinDbg做而你不能用 VS 做的事情:
- 探索对象堆(按类型、内存消耗)
- 按字符串搜索对象堆
- 查看线程 CPU 消耗
- 查看有关对象的(更详细的)信息(方法表、EEClass、大小、字段...)
- 查看内存消耗(按类型,对于 X 类型的对象,..)
- 显示所有锁定的对象
- 查看每个线程的锁计数
- 自动检测死锁(SOSEX)
- 探索垃圾收集器——代的内容,终结器队列,......
- 提取模块(如果您只有 Dump,则很有用,用于从符号服务器反编译和创建符号服务器)
- …
我可能错过了一些或添加了一些 Visual Studio 也可以做的事情,VS 一直在变得更好。但总体思路是 WinDbg 几乎可以做任何事情,尽管可能有点难以处理。这是有关托管转储的 WinDbg 命令的cheat sheet。这包括使用SOSEX 的命令,这是 WinDbg 托管调试的另一个有用扩展。
3. 使用其他工具调试转储:CDB & NTSD、DumpMiner 和 SuperDump
还有一些其他的转储文件调试工具:
- CDB和 NTSD 是类似于 WinDbg 的命令行调试器。不同之处在于 CDB 根本没有 UI,而 WinDbg 确实有一些 UI,如内存地址链接。
- DumpMiner是一个使用ClrMD库调试转储的工具。它在用户友好的 UI 中提供了许多 WinDbg 功能。它可以调查调用堆栈、线程、大对象堆、终结器、处理程序等。
- SuperDump – 还允许以用户友好的方式提供类似 WinDbg 的功能。这是一个基于云的解决方案,因此您必须将转储上传到他们的服务器才能使用它。SuperDump 包含许多功能。
WinDbg 预览
我们在本文中讨论了很多关于 WinDbg 的内容,所有示例都在经典的WinDbg 版本中展示。但是,2017 年 8 月发布了一个新版本的 WinDbg 。它现在被称为WinDbg 预览版。

新版本仍然是基于命令行的,但它包含了许多可视化、突出显示、键盘快捷键、调试窗口和新功能。不知道它是否会像在 Visual Studio 中调试一样好,但这肯定是朝着正确方向迈出的一步。
.NET 核心转储
就 .NET Core 而言,一切都与 .NET 框架一样好。您可以在 Visual Studio (2017) 和 WinDbg 中打开 .NET Core Dumps。WinDbg的唯一区别是您必须加载SOS coreclr 而不是常规clr : .loadby sos coreclr。
甚至可以在 Linux 中调试 .NET Core 转储(请参阅Sasha Goldshtein 的文章)。
总结
正如您在本文中读到的,调试转储不再自动转到WinDbg。在 2019 年,我们有许多工具可供我们使用,可以使调试工作变得更加容易。其中一些工具是 Visual Studio、DumpMiner、SuperDump和WinDbg Preview。
Crash Dumps 对我来说总是一件可怕的事情。随着岁月的流逝,我对它们越来越熟悉,慢慢地它们变得不那么可怕,也更加友好。所以我希望这篇文章能帮助你与 Dump Files 成为更好的朋友。

浙公网安备 33010602011771号