【问题标题】:How does exception dispatching change with an unhandled exception handler?未处理的异常处理程序如何改变异常分派?
【发布时间】:2016-03-06 00:10:54
【问题描述】:

简而言之,MSDN describes exception dispatching 用于这样的用户模式应用程序:

  1. 调试器收到第一次机会异常的通知(如果附加)
  2. 又名异常处理程序。 try/catch 被调用(如果可用)
  3. 调试器收到第二次机会异常通知(如果附加)
  4. 系统关心未处理的异常(通常:终止进程)

此序列不考虑未处理的异常处理程序的存在。当存在未处理的异常处理程序时,异常分派如何变化?

【问题讨论】:

  • 我相信winapi 标记具有误导性,因为您只是在讨论CLR 中的异常处理。在内部,Windows 使用Structured Exception Handling。虽然 CLR 异常是根据 SEH 异常实现的,但 SEH 异常和 CLR 异常暴露了不同的语义。再说一次,您的第一个链接指向 SEH,我不确定您指的是哪个异常处理(您的答案包含 C# 代码)。
  • @IInspectable:感谢您的洞察力。我不认为这种行为是特定于语言的。好的,我们有 SEH,CLR 内部使用 SEH。我不确定语义会改变什么。让我们实际一点:你说 C++ 的答案会有所不同吗?
  • 关键区别在于Exception Dispatching的第一句话:“当发生硬件或软件异常时[...]”。 C++(也可能是 C#)中的异常处理是严格同步的。 try/catch 处理程序只会捕获抛出的异常。它不会捕获硬件异常。详细信息在Exception Handling Differences 下进行了概述。这个问题的答案可能应该是使用 SEH 异常过滤器的 C 语言。

标签: windows winapi exception-handling usermode


【解决方案1】:

未处理的异常处理程序插入到位置 3。顺序是:

  1. 调试器收到第一次机会异常的通知(如果附加)
  2. 又名异常处理程序。 try/catch 被调用(如果可用)
  3. 未处理的异常处理程序(注意复数)被调用(如果可用)
  4. 调试器收到第二次机会异常的通知(如果附加)
  5. 系统关心未处理的异常(通常:终止进程)

下面的 C# 程序演示了它。根据 .NET 版本,您将收到另一个未处理异常处理程序的消息,即打印异常和调用堆栈的 .NET 框架。

using System;
namespace UnhandledException
{
    static class Program
    {
        static void Main()
        {
            Console.WriteLine("Please attach the debugger now and press Enter.");
            Console.ReadLine();            
            AppDomain.CurrentDomain.UnhandledException += (sender, e) => Unhandled1();
            AppDomain.CurrentDomain.UnhandledException += (sender, e) => Unhandled2();
            try
            {
                Console.WriteLine("Throwing now.");
                // Will cause a first chance, because in try/catch
                throw new Exception("Any exception will do");
            }
            catch (Exception)
            {
                // Will cause first chance and second chance, because in NOT try/catch
                Console.WriteLine("In catch block.");
                throw;
            }
        }

        static void Unhandled1() => Console.WriteLine("In unhandled exception handler 1");
        static void Unhandled2() => Console.WriteLine("In unhandled exception handler 2");
    }
}

调试器 (WinDbg) 中所需的命令:

.symfix
.reload
sxe clr
g; *** for the breakpoint due to attaching the debugger
g; *** first chance in try/catch
g; *** first chance outside try/catch
g; *** second chance

【讨论】:

    猜你喜欢
    • 2021-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    • 2011-11-19
    相关资源
    最近更新 更多