为什么.NET不记录StackOverflow异常的堆栈跟踪?

时间:2011-09-20 05:23:49

标签: .net stack-overflow

如果我写这个:

class Program
{
    static void Main(string[] args)
    {
        throw new Exception("lol");
    }
}

并从命令行运行exe,我在事件日志中得到两个条目。一个是应用程序错误,表示存在未处理的异常,另一个包含堆栈跟踪,源代码为.NET Runtime。

如果我写这个:

class Program
{
    static void Main(string[] args)
    {
        Recurse4Evr();
    }

    static void Recurse4Evr()
    {
        Recurse4Evr();
    }
}

我的事件日志中只有一个条目,它表示应用程序错误,并且存在堆栈溢出异常。没有第二个带有堆栈跟踪的条目,所以它基本没用。

为什么还没有记录堆栈跟踪?如果我设置DebugDiag并将其附加到我的进程然后存在堆栈溢出,则DebugDiag能够记录堆栈跟踪。显然,堆栈跟踪以某种方式可用于外部世界。如果运行时因为检测到堆栈溢出而终止进程,那么它也知道堆栈是什么。

在具有许多复杂交互的大型应用程序中,通常无法重新创建导致堆栈溢出的条件。在这种情况下,堆栈跟踪是弄清楚发生了什么的唯一方法。为什么微软决定记录这些信息并不重要?是否有合理的设计决策并不明显?

2 个答案:

答案 0 :(得分:1)

堆栈溢出被认为是不可恢复的情况,因此运行时会终止进程。

总结:

from Damien_The_Unbeliever

StackOverflowException s上的MSDN页面:

  

在.NET Framework的早期版本中,您的应用程序可以捕获StackOverflowException对象(例如,从无限递归中恢复)。但是,目前不鼓励这种做法,因为需要大量额外代码才能可靠地捕获堆栈溢出异常并继续执行程序。

     

从.NET Framework 2.0版开始,try-catch块无法捕获StackOverflowException对象,默认情况下会终止相应的进程。因此,建议用户编写代码以检测并防止堆栈溢出。例如,如果您的应用程序依赖于递归,请使用计数器或状态条件来终止递归循环。请注意,承载公共语言运行时(CLR)的应用程序可以指定CLR卸载发生堆栈溢出异常的应用程序域,并让相应的进程继续。有关更多信息,请参阅ICLRPolicyManager接口和托管公共语言运行时。


from JaredPar

从2.0开始,只能在以下情况下捕获StackOverflow异常。

  1. CLR正在托管环境中运行,其中主机特别允许处理StackOverflow异常
  2. 用户代码抛出stackoverflow异常,而不是由于实际的堆栈溢出情况(Reference

答案 1 :(得分:0)

这显然是不可能的。如果您想要堆栈跟踪,以便找到导致应用程序失效的有问题的代码,则需要附加第三方工具,如DebugDiag或AdsPlus。祝你好运,基本上没有这些工具的文档。