Structured Exception Handling
2007-01-14 20:14:46 来源:WEB开发网SEHintheBuff
若将SEH的细节都放到一起讨论,任务实在艰巨,因此,我会从简单的开始,一层一层往深里讲。如果之前从未使用过结构化异常处理,则正好心无杂念。若是用过,那就要努力将 _try、GetExceptionCode和
EXCEPTION_EXECUTE_HANDLER从脑子中扫出,假装这是一个全新的概念。Areyouready?Good。
当线程发生异常时,操作系统会将这个异常通知给用户使用户能够得知它的发生。更特别的是,当线程发生异常时,操作系统会调用用户定义的回调函数。这个回调函数想做什么就能做什么。例如,它可以修正引起异常的程序,也可以播放一段.WAV文件。无论回调函数干什么,函数最后的动作都是返回一个值告诉系统下面该干些什么(这样说并不严格,但目前可以认为是这样)。既然在用户代码引起异常后,操作系统会回调用户的代码,那这个回调函数又是什么样的呢?换句话说,关于异常都需要知道哪些信息呢?其实无所谓,因为Win32已经定义好了。异常的回调函数的样子如下:
EXCEPTION_DISPOSITION
__cdecl_except_handler(
struct_EXCEPTION_RECORD*ExceptionRecord,
void*EstablisherFrame,
struct_CONTEXT*ContextRecord,
void*DispatcherContext
);
这个函数原型来自标准Win32头文件EXCPT.H,初看上去让人有点眼晕。如果慢慢看的话,似乎情况还没那么严重。对于初学者来说,大可以忽略返回值的类型(EXCEPTION_DISPOSITION)。所需知道的就是这个函数叫_except_handler,需要四个参数。
第一个参数是一个指向EXCEPTION_RECORD的指针。这个结构体定义在WINNT.H中,定义如下:
typedefstruct_EXCEPTION_RECORD{
DWORDExceptionCode;
DWORDExceptionFlags;
struct_EXCEPTION_RECORD*ExceptionRecord;
PVOIDExceptionAddress;
DWORDNumberParameters;
DWORDExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD;
参数ExceptionCode是操作系统分配给异常的号。在WINNT.H文件中查找开头为“STATUS_”的宏就能找到一大堆这样的异常代号。例如,大家熟知的STATUS_ACCESS_VIOLATION的代号就是0xC0000005。更为完整的异常代号可以从WindowsNTDDK中的NTSTATUS.H文件里找到。EXCEPTION_RECORD结构体的第四个元素是异常发生处的地址。其余的EXCEPTION_RECORD域目前都可以忽略掉。_except_handler函数的第二个参数是一个指向establisherframe结构体的指针。在SEH里这可是个重要的参数,不过现在先不用管它。第三个参数是一个指向CONTEXT结构体的指针。CONTEXT结构体定义在WINNT.H文件中,它保存着某一线程的寄存器的值。Figure1即为CONTEXT结构体的域。当用于SEH时,CONTEXT结构体保存着发生异常时各寄存器的值。无独有偶,GetThreadContext和SetThreadContext使用的也是相同的CONTEXT结构体。第四个也是最后的一个参数叫做DispatcherContext,现在先不去管它。
Tags:Structured Exception Handling
编辑录入:爽爽 [复制链接] [打 印]更多精彩
赞助商链接