使用 Windows 调试器调试托管代码
可以使用 Windows 调试器(WinDbg、CDB 和 NTSD)调试包含托管代码的目标应用程序。 若要调试托管代码,请将 !SOS 调试扩展 (sos.dll) 和数据访问组件 (mscordacwks.dll) 与 CLR 运行时结合使用。
Windows 调试器(如 WinDbg)与 Visual Studio 调试器相互独立。 有关 Windows 调试器与 Visual Studio 调试器之间的区别的信息,请参阅适用于 Windows 的调试工具。
本文提供有关使用 Windows 调试器(WinDbg、CDB、NTSD)调试托管代码(包括 .NET Framework、.NET Core 和 .NET 5+ 应用程序)的说明。
注意
请确保使用最新版本的 Windows 调试器工具调试 .NET Framework、.NET Core 和 .NET 5+ 应用程序。 此外,请考虑使用 Visual Studio 或 Visual Studio Code 获得集成度更高的调试体验。 WinDbg 更加复杂,设置起来更加麻烦,并且通常在需要其他低级别信息时使用。
托管代码简介
托管代码与 Microsoft .NET 公共语言运行时 (CLR) 一起执行。 在托管代码应用程序中,编译器生成的二进制代码采用与平台无关的 Microsoft 中间语言 (MSIL)。
运行托管代码时,运行时将生成特定于平台的本机代码。 从 MSIL 生成本机代码的过程称为实时 (JIT) 编译。 在 JIT 编译器编译特定方法的 MSIL 后,该方法的本机代码将保留在内存中。 稍后调用此方法时,就会执行本机代码,并且不需要 JIT 编译器。
可以使用由各种软件生成者制造的多个编译器来生成托管代码。 具体而言,Microsoft Visual Studio 可以从多种不同的语言(包括 C#、Visual Basic、JScript 和具有托管扩展的 C++)生成托管代码。
每次更新 .NET Framework 时,CLR 都不会更新。 例如,.NET Framework 的 2.0、3.0 和 3.5 版都使用 CLR 的 2.0 版。 有关 .NET 版本的详细信息,请参见 .NET Framework 版本和依赖关系。 有关确定 PC 上的 .NET 版本的信息,请参阅确定安装了哪些 .NET Framework 版本。
调试托管代码
若要使用 !SOS 调试扩展调试托管代码,调试器必须加载各种组件。 用于不同 .NET Core 和原始 .NET Framework 的 !SOS 调试扩展和所需组件。 对于任一项,都将使用数据访问组件 (DAC) (mscordacwks.dll)。
.NET SDK 提供有助于调试 .NET 应用的工具。 有关详细信息,请参阅什么是 .NET SDK?。
.NET Core
- 对于 .NET Core 或 .NET 5+ 及更高版本,运行时为
coreclr.dll
。 有关详细信息,请参阅公共语言运行时 (CLR) 概述。 - .NET Core SOS 调试扩展
对于 .NET Core,有一个可用于安装 !sos.dll 的 dotnet CLI 工具。 有关详细信息,请参阅 SOS 安装程序 (dotnet-sos)。
原始 .NET Framework。
- 对于原始 .NET Framework,
clr.dll
是运行时。 - SOS 调试扩展 (sos.dll)
获取 SOS 调试扩展 (sos.dll)
SOS 调试扩展 (sos.dll) 文件不包含在所有版本的 Windows 调试工具中。 如果 sos.dll 不可用,请参阅在 Windows 上安装 SOS。
加载 SOS 调试扩展 (sos.dll)
若要调试 .NET Core 和 .NET 5+ 应用程序,需要加载适当的 SOS 调试扩展版本。
例如,对于调试器随附的包含在当前扩展搜索路径中的 !SOS 版本,将使用 .load 命令。
0:000> .load sos.dll
若要验证 SOS 调试扩展加载是否正确,请使用 .chain 命令并检查扩展 DLL 链。
...
Extension DLL chain:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll: image 4.8.9275.0, API 1.0.0, built Wed Aug 28 14:43:27 2024
[path: C:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll]
C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\8.0.8\coreclr.dll: image 8,0,824,36612 @Commit: 08338fcaa5c9b9a8190abb99222fed12aaba956c, built Tue Jul 16 11:10:19 2024
[path: C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\8.0.8\coreclr.dll]
如果调试器版本不包含 sos.dll,则可能需要指定 SOS.dll 文件的完整路径。 通常可以在 .NET Core 或 .NET Framework 安装的运行时目录中找到 SOS.dll 文件。
0:000> .load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos.dll
加载特定版本的 sos.dll
加载 sos.dll 可能很复杂,因为依赖于 sos.dll 用来与 .NET 通信的其他 DLL。 此外,所需的 DLL 版本依赖于正在调试的应用的 .NET 版本,并且计算机上可能存在多个版本的 .NET。
加载依赖 DLL 的正确版本的一种策略是要求调试器使用 sx、sxd、sxe、sxi、sxn、sxr、sx- (Set Exceptions)[../debuggercmds/sx--sxd--sxe--sxi--sxn--sxr--sx---set-exceptions-.md] 命令在第一个 .NET clr 通知 (CLRN) 出现时中断操作。 附加到目标 .NET 应用程序后,将在第一次中断后使用此命令。
0:000> sxe CLRN
接下来继续执行并等待中断发生。
0:000> g
中断发生时,禁用 clr 通知中断,因为我们知道已加载 clr.dll(或 coreclr.dll)。
0:000> sxd CLRN
在此上下文中使用调试器时,使用 .loadby 从同一“附近”目录位置加载 !sos。
0:000> .loadby sos clr
另一个选项是使用 .cordll(控制 CLR 调试)通过提供目标框架位置的路径来加载 CLR 调试 DLL。
0:000> .cordll -ve -u -lp C:\Windows\Microsoft.NET\Framework\v4.0.30319\
CLRDLL: Loaded DLL C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscordacwks.dll
Automatically loaded SOS Extension
CLR DLL status: Loaded DLL C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscordacwks.dll
使用 SOS 调试扩展
若要验证 SOS 调试扩展是否正确加载,请输入 .chain 命令。
0:000> .chain
Extension DLL search Path:
C:\Program Files\Debugging Tools for Windows (x64);...
Extension DLL chain:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll: image 4.8.9275.0, API 1.0.0, built Wed Aug 28 14:43:27 2024
[path: C:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll]
...
.NET 符号文件
符号文件对于调试至关重要。 对于 .NET Framework、.NET Core 和 .NET 5+ 应用程序,可以从 Microsoft 的公共符号服务器检索必要的符号文件。 使用以下命令设置符号路径和回显符号加载。
.symfix
!sym noisy
.reload
测试 .NET Core !sos 扩展
若要测试 SOS 调试扩展,请输入 !sos.help。
0:000> !sos.help
-------------------------------------------------------------------------------
SOS is a debugger extension DLL designed to aid in the debugging of managed
programs. Functions are listed by category, then roughly in order of
importance. Shortcut names for popular functions are listed in parenthesis.
Type "!help <functionname>" for detailed info on that function.
Object Inspection Examining code and stacks
----------------------------- -----------------------------
DumpObj (do) Threads
DumpArray (da) ThreadState
DumpStackObjects (dso) IP2MD
DumpHeap U
DumpVC DumpStack
GCRoot EEStack
ObjSize CLRStack
FinalizeQueue GCInfo
PrintException (pe) EHInfo
TraverseHeap BPMD
COMState
然后尝试 SOS 调试扩展提供的命令之一。 例如,可以尝试 .NET Core SOS 调试扩展提供的 !sos.DumpDomain 或 !sos.Threads 命令。
0:000> !sos.DumpDomain
--------------------------------------
System Domain: 7565d980
LowFrequencyHeap: 7565dca4
HighFrequencyHeap: 7565dcf0
StubHeap: 7565dd3c
Stage: OPEN
Name: None
--------------------------------------
Shared Domain: 7565d620
LowFrequencyHeap: 7565dca4
HighFrequencyHeap: 7565dcf0
StubHeap: 7565dd3c
Stage: OPEN
Name: None
Assembly: 00fa5e78 [C:\WINDOWS\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll]
ClassLoader: 00fa5f40
Module Name
73571000 C:\WINDOWS\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
0:000> !sos.Threads
ThreadCount: 2
UnstartedThread: 0
BackgroundThread: 2
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
Lock
ID OSID ThreadOBJ State GC Mode GC Alloc Context Domain Count Apt Exception
0 1 4538 00f91110 20220 Preemptive 02FE1238:00000000 00f58be0 1 Ukn
7 2 250c 00f9da88 21220 Cooperative 00000000:00000000 00f58be0 1 Ukn (Finalizer)
测试 .NET Framework !sos 扩展
若要测试 SOS 调试扩展,请输入 !sos.help。 然后尝试 SOS 调试扩展提供的命令之一。 例如,可以尝试 !sos.sostatus 或 !sos.threads 命令。
0:030> !soshelp
crashinfo Displays the crash details that created the dump.
help, soshelp <command> Displays help for a command.
loadsymbols <url> Loads symbols for all modules.
logclose <path> Disables console file logging.
logging <path> Enables/disables internal diagnostic logging.
logopen <path> Enables console file logging.
maddress Displays a breakdown of the virtual address space.
modules, lm Displays the native modules in the process.
registers, r Displays the thread's registers.
runtimes <id> Lists the runtimes in the target or changes the default runtime.
setclrpath <path> Sets the path to load coreclr DAC/DBI files.
setsymbolserver, SetSymbolServer <url> Enables and sets symbol server support for symbols and module download.
sosflush Resets the internal cached state.
sosstatus Displays internal status.
threads, setthread <thread> Lists the threads in the target or sets the current thread.
备注
有时,托管代码应用程序会加载多个版本的 CLR。 在这种情况下,必须指定要加载的 DAC 版本。 有关详细信息,请参阅 .cordll 和 Clrver.exe(CLR 版本工具)。