这通常是我使用 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
命令 Go 并使用您的应用程序,直到您收到 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 和托管调试扩展的文章。