_try_except原理
调用_except_handle3
这个异常处理函数,这里并不是每个编译器的异常处理函数都是相同的,然后存入结构体,将esp的值赋给fs:[0]
,再就是提升堆栈的操作
每个使用 _try _except
的函数,不管其内部嵌套或反复使用多少_try _except
,都只注册一遍,即只将一个 _EXCEPTION_REGISTRATION_RECORD
挂入当前线程的异常链表中(对于递归函数,每一次调用都会创建一个 _EXCEPTION_REGISTRATION_RECORD
,并挂入线程的异常链表中)。
typedef struct _EXCEPTION_REGISTRATION_RECORD {
struct _EXCEPTION_REGISTRATION_RECORD *Next;
PEXCEPTION_ROUTINE Handler;
} EXCEPTION_REGISTRATION_RECORD;
可以看到只有一个异常处理函数
那么这里编译器是如何做到只用一个异常处理函数的呢?编译器把原来_EXCEPTION_REGISTRATION_RECORD
结构进行了拓展,添加了三个成员
struct _EXCEPTION_REGISTRATION{
struct _EXCEPTION_REGISTRATION *prev;
void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_REGISTRATION, PCONTEXT, PEXCEPTION_RECORD);
struct scopetable_entry *scopetable;
int trylevel;
int _ebp;
};
新堆栈结构如下
scopetable
struct scopetable_entry
{
DWORD previousTryLevel //上一个try{}结构编号
PDWRD lpfnFilter //过滤函数的起始地址
PDWRD lpfnHandler //异常处理程序的地址
}
查看地址可以发现有三个结构体
存储着的正式异常函数的开始地址和结束地址
第一个值previousTryLevel
是上一个try
结构的编号,这里如果在最外层就是-1,如果在第二层就是0,如果在第三层就是1,以此类推