【发布时间】:2010-09-11 14:04:16
【问题描述】:
在 .NET 中遇到一些 StackOverflowExceptions 后,我注意到它们完全绕过了 .NET 提供的未处理异常处理程序(Application.ThreadException / AppDomain.UnhandledException)。 这非常令人不安,因为我们在这些异常处理程序中有关键的清理代码。
有什么办法可以克服吗?
【问题讨论】:
在 .NET 中遇到一些 StackOverflowExceptions 后,我注意到它们完全绕过了 .NET 提供的未处理异常处理程序(Application.ThreadException / AppDomain.UnhandledException)。 这非常令人不安,因为我们在这些异常处理程序中有关键的清理代码。
有什么办法可以克服吗?
【问题讨论】:
有三种所谓的“异步异常”。那是 ThreadAbortException、OutOfMemoryException 和提到的 StackOverflowException。这些异常允许出现在代码中的任何指令中。
而且,还有一种方法可以克服它们:
最简单的是 ThreadAbortException。当前代码在 finally 块中执行时。 ThreadAbortExceptions 有点“移动”到 finally 块的末尾。所以 finally 块中的所有内容都不能被 ThreadAbortException 中止。
要避免 OutOfMemoryException,您只有一种可能:不要在堆上分配任何东西。这意味着您不能创建任何新的引用类型。
要克服 StackOverflowException,您需要框架的帮助。这种帮助体现在受约束的执行区域中。所需的堆栈是在在实际代码执行之前分配的,另外还确保代码已经 JIT 编译,因此可以执行。
在Constrained Execution Regions中执行代码有3种形式(抄自BCL Team Blog):
您可以在这些博客文章中找到更多信息:
Constrained Execution Regions and other errata [Brian Grunkemeyer] 在 BCL 团队博客上。
Joe Duffy 的关于 Atomicity and asynchronous exception failures 的博客,其中他很好地概述了 .net 框架中的异步异常和稳健性。
【讨论】:
不是真的;堆栈溢出或 CLR 本身发生内存不足异常意味着出现严重错误(当我是个笨蛋并创建递归属性时,我通常会得到它)。
当此状态发生时,CLR 无法分配新的函数调用或内存以使其能够调用异常处理程序;这是一个“我们必须现在停止”的场景。
但是,如果您自己抛出异常,您的异常处理程序将被调用。
【讨论】:
堆栈溢出不是您可以从中恢复的东西,因为它无法分配更多堆栈内存来调用您的异常处理程序。
你唯一能做的就是找出原因并完全防止它发生(例如小心递归,不要在堆栈上分配大对象)。
【讨论】:
blowdart 把它钉在了上面。 Dumbass 递归属性,他喜欢这样称呼它。真的只是输入代码太快的问题。
private Thing _myThing = null;
Public Thing MyThing
{
get{
return this.MyThing;}
set{
this.MyThing = value;}
}
【讨论】: