.NET中的StackOverflowException

时间:2008-09-20 09:33:01

标签: .net exception

在.NET中遇到一些StackOverflowExceptions后,我注意到它们完全绕过.NET提供的未处理的异常处理程序(Application.ThreadException / AppDomain.UnhandledException)。 这非常令人不安,因为我们在这些异常处理程序中有关键的清理代码。

有没有办法克服这个问题?

4 个答案:

答案 0 :(得分:25)

有三种所谓的“异步异常”。这是ThreadAbortException,OutOfMemoryException和提到的StackOverflowException。允许在代码中的任何指令处发生这些异常。

而且,还有一种方法可以克服它们:

最简单的是ThreadAbortException。当前代码在finally块中执行时。 ThreadAbortExceptions有点“移动”到finally块的末尾。因此,最终块中的所有内容都不能被ThreadAbortException中止。

为避免OutOfMemoryException,您只有一种可能性:不要在堆上分配任何内容。这意味着您不能创建任何新的引用类型。

要克服StackOverflowException,您需要Framework的一些帮助。这种帮助体现在约束执行区域中。在执行实际代码之前,分配了所需的堆栈,并且还确保代码已经过JIT编译,因此可以执行。

在Constrained Execution Regions中执行代码有三种形式(从BCL Team Blog复制):

  • ExecuteCodeWithGuaranteedCleanup,一个try / finally的堆栈溢出安全形式。
  • 尝试/结束块之后立即调用RuntimeHelpers.PrepareConstrainedRegions。 try块不受约束,但是try的最后捕获,最后和故障块都是。
  • 作为一个关键的终结器 - CriticalFinalizerObject的任何子类都有一个在分配对象实例之前急切准备的终结器。
    • 一个特例是SafeHandle的ReleaseHandle方法,这是一个在分配子类之前急切准备的虚方法,并从SafeHandle的关键终结器调用。

您可以在以下博文中找到更多信息:

Constrained Execution Regions and other errata [Brian Grunkemeyer]在BCL团队博客上。

Joe Duffy关于Atomicity and asynchronous exception failures的博客,他非常了解.net框架中的异步异常和健壮性。

答案 1 :(得分:18)

不是真的;在CLR本身内发生堆栈溢出或内存不足异常意味着出现了严重错误(当我成为笨蛋并创建递归属性时,我通常会得到它)。

当发生这种状态时,CLR无法分配新的函数调用或内存以使其能够调用异常处理程序;这是“我们必须停止现在”的情景。

但是,如果您自己抛出异常,则会调用异常处理程序。

答案 2 :(得分:1)

stackoverflow不是你可以恢复的东西,因为它甚至不能分配更多的堆栈内存来调用你的异常处理程序。

你唯一可以做的就是追查原因并防止它发生(例如,对于递归,并且不在堆栈上分配大对象)。

答案 3 :(得分:1)

blowdart将它钉在上面。 Dumbass递归财产,因为他喜欢称之为。打包代码真的只是一个问题。

private Thing _myThing = null;

Public Thing MyThing
{
   get{
        return this.MyThing;}
   set{
        this.MyThing = value;}
}