Windows异常分发 - First Chance Exception vs Second Chance Exception

本文深入探讨了使用Visual Studio运行程序时,在Output中常见到的类名为FirstChanceException的输出所代表的含义。具体解释了FirstChanceException和SecondChanceException的区别及其对开发人员的意义,同时详细介绍了Windows异常分发处理的机制,包括异常从发生到最终处理的完整流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过visualstudio运行程序,经常会在output里面看到类似的输出,

A first chanceexception of type 'System.DivideByZeroException' occurred in xxx.dll


我们的问题

  • 什么是first chance exception?
  • 什么是second chance exception?
  • 他们对开发人员的意义是什么? 

异常分发处理的机制

理解windows异常分发机制主要要看明白这张图(摘自Windows Internal Chapter 3),


异常分发的流程如下

1.所有的异常都会根据系统的idt(interrupt dispatch table)分发到陷阱处理器(trap handler),系统的idt可以通过内核调试命令!idt查看。

2. Trap handler将异常信息交给内核中的异常分发器,异常分发器先查看是否存调试器与之相关联,如果存在则将控制权交给调试器,这就是第一次异常发生(first chance exception)这样做使得我们在异常发生之初,自定义异常处理之前得到控制权可以查看异常的原始信息。

3.如果没有相关联的调试器或者调试器未对该异常进行处理,分发器开始基于栈查找异常处理器。

4.如果没有找到异常处理器或者异常处理器为对其进行处理,分发器再次尝试分发给调试器端口,第二次异常发生(second chance exception)。

5.如果没有调试器或者调试器没有处理第二次异常,分发器将该异常发送给环境子系统的异常端口用来转换成各种不同的环境子系统相应的错误提示代码。

6.如果环境子系统对异常为进行处理,分发器分发给内核默认异常处理器。该异常处理器是在线程启动的时候注册的。可以通过system internal提供的process explore察看线程的启动地址。

 

线程的启动代码大致如下

VOID RtlUserThreadStart(VOID){

    LPVOID lpStartAddr = (R/E)AX; // Located in the initial thread context structure
    LPVOID lpvThreadParm = (R/E)BX; // Located in the initial thread context structure
    LPVOID lpWin32StartAddr;

    lpWin32StartAddr = Kernel32ThreadInitThunkFunction ? Kernel32ThreadInitThunkFunction :
lpStartAddr;
    __try {

        DWORD dwThreadExitCode = lpWin32StartAddr(lpvThreadParm);
        RtlExitUserThread(dwThreadExitCode);

    } __except(RtlUnhandledExceptionFilter(
            GetExceptionInformation())) {

        RtlExitUserProcess(GetExceptionCode());
    }
}
void Win32StartOfProcess(
    LPTHREAD_START_ROUTINE lpStartAddr,
    LPVOID lpvThreadParm){

    lpStartAddr(lpvThreadParm);
}

该异常处理逻辑会根据以下注册表项进行相应的处理,例如我机器上的注册表项配置为visualstudio debug,异常发生的时候vs会启动让用户来决定是否要attach到进程查看异常。

HKLM\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\AeDebug

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值