【问题标题】:List of exceptions that CAN'T be caught in .NET.NET 中无法捕获的异常列表
【发布时间】:2011-11-15 14:33:21
【问题描述】:

在 .NET 中不能捕获的异常列表是什么?或者我在哪里可以找到这样的列表?

【问题讨论】:

  • NullReferenceException 可以被抓到。是什么让您认为不可能?
  • 为什么需要这样的列表?捕获并处理您可以处理的异常,捕获并记录您无法处理的异常,并让操作系统在出现灾难性错误以至于无法捕获异常时将您的进程从轨道上删除。
  • 或者你的意思是不应该而不是不能
  • 我来自 Java,那里有无法捕获的运行时异常和其他可以捕获的异常。只是想知道 .NET 是否相似,如果是,哪些异常的行为类似于 Java 的运行时异常。
  • @Denis:你绝对可以在 java 中捕获 RuntimeException,就像任何其他 Throwable 一样; RuntimeException 的特殊之处在于它们没有被检查,即你可以在方法声明中不声明它们就抛出它们。

标签: c# .net vb.net


【解决方案1】:

唯一不能直接捕获的异常是(一个框架抛出的)StackOverflowException。从逻辑上讲,这是有道理的,因为此时堆栈中没有空间来处理异常。来自文档:

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

ThreadAbortException 可以被捕获,但总是会被重新提升,因此具有独特的行为。来自文档:

ThreadAbortException 是一个可以被捕获的特殊异常,但它会在 catch 块结束时自动再次引发。

另请注意,某些AccessViolationException 实例是损坏状态异常,默认情况下可能无法处理。这些可以处理,但需要通过属性进行额外处理。详情请见Handling Corrupted State Exceptions

【讨论】:

  • 请注意,您可以通过调用 Thread.ResetAbort() 来禁止 ThreadAbortException 重新抛出。 (注意:不要那样做。)
  • 既然这是公认的答案,你可以添加 AccessViolationException (stackoverflow.com/questions/3469368/…)
  • @Simon Thouhg 你经常可以用HandleProcessCorruptedStateExceptions 抓到他们——所以他们不是不可能抓到的
  • 所以你认为在这种情况下不值得一提?
  • 也“您可以毫无问题地捕获 NullReferenceException。”不再与已编辑的问题相关
【解决方案2】:

NullReferenceException 当然可以被抓到。你是从哪里得到这个想法的?

try {} catch {} 将捕获非托管异常以及托管异常(请注意,catch 上没有异常子句)。

唯一无法捕获的是StackOverflowException,而TreadAbortException在捕获结束时被重新抛出。

【讨论】:

  • 这不是真的。堆栈溢出将在您捕获异常之前停止执行。所以至少有一个。
  • @Oded,在某些极端情况下,我认为 Enivornment.FailFast 和 System.StackOverflow 不会发生这种情况
  • @Oded:这只是那些有趣的花絮之一 - 我使用 StackOverflow 可能会以某种方式被抓住 - 在某些情况下它会让生活变得更轻松:(
  • @Reed 确定你可以...在递归函数中保留一个计数器(每次输入时递增)如果 counter >= 然后抛出 new LikelyStackOverflowException() - 你会得到堆栈跟踪。
  • @Denis:这与捕获“真正的” StackOverflowException 不同。当然你可以自己管理,但这不是我的建议;)
【解决方案3】:

ThreadAbortException

注意:

ThreadAbortException 是一个特殊的异常,可以被捕获,但是它 将在 catch 块结束时自动再次升高。什么时候 引发此异常,运行时执行所有 finally 块 在结束线程之前。

【讨论】:

  • 我什至不会算这个,因为它可以被抓住,只是它有被重新抛出的副作用。尽管如此,+1 还是不错的发现。
  • 这个可以被抓到,重投行为可以通过调用Thread.ResetAbort()来抑制
【解决方案4】:

嗯,有一些异常,即使你捕捉到它们,它们也会被重新抛出。 StackOverflowException 是我唯一能想到的 atm。可能是ThreadAbortedException

【讨论】:

    【解决方案5】:

    试试这个...(在 .NET Core 2.0 上测试)

    System.Runtime.Serialization.FormatterServices.GetUninitializedObject(typeof(Type).GetType()).ToString()
    

    一个忽略所有 try/catch/finally 块的System.ExecutionEngineException 被抛出,即使它已被弃用,说运行时不再抛出这种类型的异常。很奇怪吧?

    原因可能是typeof(Type).GetType() 返回typeof(System.RuntimeType),这是一个内部类型和运行时内部。 System.Runtime.Serialization.FormatterServices.GetUninitializedObject 对这些类型(如 typeof(string))的参数进行了验证,但开发人员可能忘记检查这种非公共类型。结果,返回无效的System.RuntimeType。当调用ToString 时,无效状态会导致运行时崩溃。

    【讨论】:

    • 不幸的是,System.Runtime.Serialization.FormatterServices 将在 .NET 7 中被淘汰并在 .NET 8 中抛出 PlatformNotSupportedException,所以这不会持续很长时间...github.com/dotnet/designs/blob/master/accepted/2020/…
    • 很好奇。我想知道什么会取代GetUninitializedObject,因为我见过的许多高性能序列化程序都依赖于它
    • 哇,太好了,还在 .net core 6 上工作
    【解决方案6】:

    由于可访问性而无法按类型引用的任何异常都无法显式捕获,但可以使用基本 Exception 类型捕获。

    例如,代码契约框架中的ContractException 特意将internal 添加到其程序集中,这样您就无法尝试显式捕获它。

    【讨论】:

      【解决方案7】:

      我不知道你为什么提到NullReferenceExceptionsNullReferenceExceptions 是我发现的主要异常之一。我能想到的唯一一个是内存不足异常或StackOverflow,因为一旦内存不足,执行就会停止,因此很有可能异常可以不要被抓住。

      【讨论】:

        【解决方案8】:

        在某些情况下无法捕获 SEHException。它可以由非托管代码抛出。关于这个主题的一个很棒的 SO 线程出现在这里:SEHException not caught by Try/Catch

        【讨论】:

          猜你喜欢
          • 2010-10-29
          • 1970-01-01
          • 2011-04-19
          • 2021-10-09
          • 2011-11-24
          • 1970-01-01
          • 1970-01-01
          • 2021-09-17
          相关资源
          最近更新 更多