.NET中的StackOverflowException

时间:2020-03-06 14:28:51  来源:igfitidea点击:

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

有什么办法可以克服这个问题?

解决方案

并不真地; CLR本身内部发生堆栈溢出或者内存不足异常,则意味着发生了严重错误(通常,当我笨拙并创建了递归属性时,我会得到该错误)。

当此状态发生时,CLR无法分配新的函数调用或者内存以使其能够调用异常处理程序;这是"我们必须立即停止"的情况。

但是,如果我们自己抛出异常,则将调用异常处理程序。

我们不能从stackoverflow中恢复,因为它无法分配更多的堆栈内存来甚至调用异常处理程序。

我们唯一能做的就是找出原因并完全避免(例如,小心递归,并且不要在堆栈上分配大对象)。

共有三种所谓的"异步异常"。那是ThreadAbortException,OutOfMemoryException和提到的StackOverflowException。这些异常可以在代码中的任何指令中发生。

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

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

为避免OutOfMemoryException,我们只有一种可能性:不要在堆上分配任何东西。这意味着我们不允许创建任何新的引用类型。

要克服StackOverflowException,我们需要框架提供一些帮助。此帮助在受约束的执行区域中体现。在执行实际代码之前分配了所需的堆栈,此外还确保了该代码已经JIT编译,因此可用于执行。

有三种形式可以在约束执行区域中执行代码(从BCL团队博客复制):

  • ExecuteCodeWithGuaranteedCleanup,try / finally的堆栈溢出安全形式。
  • 在try / finally块之前,立即调用RuntimeHelpers.PrepareConstrainedRegions。 try块不受约束,但最终所有捕获都得到了解决,而该try的故障块受到了限制。

我们可以在以下博客文章中找到更多信息:

BCL团队博客中的约束执行区和其他勘误表[Brian Grunkemeyer]。

Joe Duffy的有关原子性和异步异常失败的Weblog,他对.net Framework中的异步异常和健壮性进行了很好的概述。

吹牛把它钉在上面。他喜欢称其为Dumbass递归属性。真的只是输入代码太快的问题。

private Thing _myThing = null;

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