22

MSDN 声明StackOverflowException 不能被从 .NET Framework 2 开始的 try-catch 块捕获。

从 .NET Framework 2.0 版开始,StackOverflowException 对象无法被 try-catch 块捕获,并且默认情况下会终止相应的进程。

是否还有其他具有相同行为的异常?

4

1 回答 1

37

是的,还有一些其他的:

  • ThreadAbortedException 是特殊的。除非 catch 块调用 ResetAbort(),否则它总是会在被捕获时重新引发。当 CLR 粗鲁地中止线程时,它是完全无法捕获的。例如,当 AppDomain 被卸载时完成,通常在程序退出时完成。

  • 由本机代码启动的线程中的非托管代码引发的任何本机异常都是无法捕获的。这里的常见场景是启动自己的线程的 COM 组件。CLR 无法捕获此类异常,它不了解线程并且无法注入 catch 块。如果本机代码未捕获异常,则 Windows 将终止该进程。

  • 终结器抛出的任何异常,除非它们是关键终结器。他们将中止终止进程的终结器线程。

  • 从 .NET 4.0 开始,ExecutionEngineException 是无法捕获的。当 CLR 检测到其内部数据结构被破坏时,它会抛出它。最常见的情况是垃圾收集器忙时引发的 AccessViolationException。当 GC 堆被破坏时继续执行托管代码是一个冒险的提议,并且可以利用,.NET 4 完全取消了它。

  • 从 CLR 的 .NET 4.0 版本开始,但也可能存在于与早期版本互操作的非托管代码中,Microsoft 的安全 CRT 可以在检测到安全问题时立即终止程序。这实际上并不是一个异常,该过程会立即终止,因为代码认为该过程已受到损害并且无法安全地处理异常。一个常见的情况是原生函数的堆栈帧被破坏,这是原生代码中的一个常见问题,被病毒代码用来修改返回地址以运行任意代码。一种称为“堆栈缓冲区溢出”的攻击场景。在 .NET 4.0 发布初期,CLR 代码中有一些误报,但我已经有一段时间没有看到了。您可以通过编写超出范围的内容自己触发此类中止堆栈分配

  • 非常臭名昭著的是,当您在 64 位操作系统上的 WOW64 仿真层中以 32 位模式运行代码并且附加了调试器时,Windows 消息处理程序会引发异常。以 Winforms 中麻烦的 Load 事件而闻名,但也出现在其他消息和其他运行时环境中。丑陋的细节在这个答案中。

  • 从 .NET 4.5 开始,Microsoft 将异常归类为损坏状态异常(CSE)。它们可以被捕获,但这只能由顶级异常处理程序完成,该处理程序除了为用户的利益生成诊断并无条件终止应用程序外,什么也不做。本杂志文章中提供了背景资料。

  • 在您的代码开始运行之前由抖动引发的任何异常都无法被捕获或报告。无法编译 Main() 方法是常见的情况,通常是 FileNotFoundException。

于 2012-11-26T14:36:35.440 回答