C# 内存转储分析方法 C#如何使用WinDbg分析dump文件

11次阅读

必须用 winDbg Preview 或 WinDbg 10 分析 C# dump;.net Framework 可用 WinDbg Legacy 配匹配版本 SOS.dll,.NET Core/5+ 必须用 WinDbg Preview 并通过 dotnet-sos 安装扩展,且位数需与 dump 一致。

C# 内存转储分析方法 C#如何使用WinDbg分析dump文件

WinDbg 装什么版本才能分析 C# dump

必须用 WinDbg Previewmicrosoft Store 版)或 WinDbg 10windows SDK 自带),旧版 WinDbg Legacy 对 .NET Core/.NET 5+ 支持极差,连 clrstack 都可能报 Failed to load data access DLL

关键点:

  • .NET Framework 程序可用 WinDbg Legacy + SOS.dll(路径需匹配运行时版本,如 C:WindowsMicrosoft.NETFramework64v4.0.30319SOS.dll
  • .NET Core 3.1+ / .NET 5+ 必须用 WinDbg Preview,它内置 dotnet-sos 和自动扩展加载能力
  • 32 位 dump 必须用 32 位 WinDbg,64 位 dump 必须用 64 位 WinDbg——混用直接卡在 .loadby sos coreclr 失败

怎么让 WinDbg 正确加载 SOS / DAC 扩展

不是所有 dump 都能直接敲 !clrstack。常见失败原因是 DAC(Data Access Component)没找到,尤其 .NET Core 程序的 dump 缺少运行时符号或未部署 dotnet-sos

实操步骤:

  • 先执行 .symfix; .reload 确保符号路径正确(默认走 Microsoft 服务器)
  • 对 .NET Core/.NET 5+:运行 dotnet-sos install(需已装 .NET SDK),然后在 WinDbg 中执行 .load C:UsersXXX.dotnetsossos.dll
  • 对 .NET Framework:用 .loadby sos clr(托管进程)或 .loadby sos mscorwks(.NET 2.0)
  • 验证是否成功:!eeversion 应输出运行时版本;!dumpheap -stat 不报错即 OK

快速定位 C# 崩溃/高 CPU/内存泄漏的命令组合

别一上来就 !dumpheap -stat——容易卡死或返回无意义数据。按问题类型选命令链:

  • 崩溃(AccessViolation / AV)!analyze -v → 看 FAULTING_IPSTACK_TEXT → 再用 !u 地址 反汇编托管方法(需 PDB 在符号路径中)
  • 高 CPU~*e !clrstack 查所有线程托管 → 找重复出现的调用(比如都在 System.Threading.WaitHandle.WaitOne 或死循环里)
  • 内存泄漏!dumpheap -stat 看大头类型 → 记下类型名(如 Myapp.CacheItem)→ !dumpheap -type MyApp.CacheItem → 拿几个对象地址 → !gcroot 地址 查谁在引用它

注意:!gcroot 输出里如果出现 Finalizer QueueHandleTable,大概率是未释放的 IDisposable事件订阅泄漏。

为什么 !dumpobj 显示字段全是 0x0 或乱码

这不是 WinDbg 问题,是 dump 缺少调试信息或对象已被 GC 回收但内存未覆写。常见于:

  • Release 编译且未生成 PDB,或 PDB 路径不对 → .sympath+ C:pathtopdbs + .reload /f
  • 对象在 Gen 0,而 dump 是 MiniDumpWithHeap 类型(不包含完整)→ 必须用 Full Dump(任务管理器右键 → “创建转储文件”,或 procdump -ma
  • 字段是 String引用类型,但 !dumpobj 只显示引用地址 → 需再对地址执行一次 !dumpobj,或用 !do(简写)

真正难的是跨 AppDomain 或跨上下文的对象引用链,这时候 !gcroot 可能只显示 DOMAIN(000001234567890),得结合源码确认生命周期管理逻辑。

text=ZqhQzanResources