我正在使用Windbg(具有sos扩展),并尝试调试崩溃的应用程序。我能够转储引发异常的调用的IL,并且通过检查代码,如果可以转储评估堆栈的内容,似乎可以获得所需的信息。WinDbg&sos可以做什么?
这是我所做的:
开始WinDbg
附加到崩溃的进程
loadby sos mscorwks (加载sos扩展名)
!token2ee theModuleName 0600009a (其中,ModuleName是我正在调试的应用程序(和程序集)的名称,9a是Windows错误报告工具报告的崩溃方法的方法偏移量。我得到以下输出:
模块:000e2c3c(theApplicationName.exe)
令牌:0x0600009a方法描述
:000e67c8
名称:MyNamespace.MyClassName.theCulpritFn(MyOtherClass)
JITTED代码地址:0081b1d0
!dumpil 00e67c8 (为相关方法转储了IL)。这是输出:
// .. // .. the previous code omitted for brevity .catch { IL_0071: stloc.0 IL_0072: nop IL_0073: ldstr "Can't set CurrentServer property for: " IL_0078: ldarg.0 IL_0079: ldfld MyNamespace.MyClassName::_currentServer IL_007e: brtrue.s IL_0087 IL_0080: ldstr "" IL_0085: br.s IL_0092 IL_0087: ldarg.0 IL_0088: ldfld MyNamespace.MyClassName::_currentServer IL_008d: callvirt MyNamespace.MyOtherClass::get_Name IL_0092: call System.String::Concat IL_0097: ldloc.0 IL_0098: newobj MyNamespace.MySpecialExceptionType::ctor IL_009d: throw }
问题是:在抛出异常之前,我是否有办法查看堆栈中已推送的内容。如果我没记错的话,传入异常构造函数的参数应该是评估堆栈上索引0处的局部变量。
PS:当我尝试调用!clrstack -a时,出现一条消息:无法遍历托管堆栈。当前线程可能不是托管线程。您可以运行!threads来获取进程中托管线程的列表。
谢谢!
您需要确定并选择正确的线程。当前线程的ID显示在WinDbg提示符中。
!threads
将显示应用程序中的所有托管线程。一旦确定,您就可以使用~Xs
X是该线程的WinDbg ID 来切换线程。
!clrstack
将显示堆栈跟踪。如果要使用本地语言和/或参数,请使用-l
/ -p
(或-a
同时使用两者)。
您可以遍历所有线程,并使用列出它们的调用堆栈~*e!clrstack
。
如果局部/参数不能满足您的需求,请使用!dso
来显示推入堆栈的对象。