这通常是我使用 WinDbg 来追踪的,否则它只是一个猜谜游戏。下面是一个快速演练,应该可以为您指明正确的方向。
WinDbg 是适用于 Windows 的调试器,适用于调试托管和非托管代码。它也非常适合检查故障转储。让我们从一个示例程序开始。
class Program
{
static void Main(string[] args)
{
IWillStackOverflow(0);
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
static int IWillStackOverflow(int i)
{
return IWillStackOverflow(i + 1);
}
}
这是一个非常人为的例子,但让我们继续吧。它确实堆栈溢出,也没有提供堆栈跟踪。这就是 WinDbg 的用武之地。首先您需要安装它,它是 Windows SDK 中调试工具的一部分。有两个版本,x64 和 x86。您需要运行与您的应用程序位数相匹配的那个。
在 WinDbg 中,使用 File -> Open Executable 并运行附加了 WinDbg 的可执行文件。一旦您的应用程序加载,调试器就会中断,您可以使用g 命令转到并使用您的应用程序,直到您收到 StackOverflowException。不过,在你这样做之前,请确保你的符号是正确的 - 通常运行 .symfix+ 会更正它,然后你就可以走了。
当您收到 StackOverflowException 时,调试器将在引发异常的线程上中断,消息将如下所示:
(cc0.b00):堆栈溢出 - 代码 c00000fd(第一次机会)
现在我们可以使用此命令加载托管调试扩展(我假设您使用的是 .NET Framework 4.0 或 4.5):
.loadby sos clr
并致电!clrstack。在本例中,输出为:
000000d440c76040 00007ffb282b0111 StackOverflower.Program.IWillStackOverflow(Int32) [Program.cs @ 20]
000000d440c76080 00007ffb282b0111 StackOverflower.Program.IWillStackOverflow(Int32) [Program.cs @ 20]
000000d440c760c0 00007ffb282b0111 StackOverflower.Program.IWillStackOverflow(Int32) [Program.cs @ 20]
..Repeat thousands of times..
所以我们在 StackOverflowException 发生时拥有托管堆栈。
如果您的应用程序不太容易 StackOverflow,您可以配置 ADPlus 以在 StackOverflowException 发生时对您的应用程序进行内存转储。 ADPlus 是另一个重磅工具,但它很有效。首先你需要一个 ADPlus 的配置,这里是一个例子:
<ADPlus>
<!-- Add log entry, log faulting thread stack and dump full on first chance StackOverflow -->
<Exceptions>
<Config>
<!-- Use sov for stack overflow exception -->
<Code> sov </Code>
<Actions1> Log;Stack;FullDump </Actions1>
<!-- Depending on what you intend - either stop the debugger (Q or QQ) or continue unhandled (GN) -->
<ReturnAction1> GN </ReturnAction1>
< Config>
</Exceptions>
</ADPlus>
此配置示例最初由用户 jaskis 在 MSDN 论坛上发布:http://blogs.msdn.com/b/jaskis/archive/2010/08/11/cwa-ends-up-with-blank-screen-on-browser-on-iis-7.aspx
然后使用命令行使用配置启动您的应用程序。
这只是一个例子,WinDbg 是一个非常强大的工具,虽然它有一点学习曲线。互联网上有很多很好的资源来掌握它。 Tess Ferrandez 在她的博客中有很多关于 WinDbg 和托管调试扩展的文章。