Win32构造化非常处理(SEH)探秘(上)[VC/C++编程]
本文“Win32构造化非常处理(SEH)探秘(上)[VC/C++编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
在 Win32 操作系统供应的全部功效中,利用最遍及但最贫乏文档描写的大概就是构造化非常处理了(SEH),当你考虑 Win32 构造化非常处理时,你大概会想到诸如 _try,_finally 以及 _except 这些术语.你能在任何有关 Win32 的书中发现对 SEH 很好的描写(即便是 remedial).即就是 Win32 SDK 也具有有相当完好的利用 _try,_finally 和 _except 举行构造化非常处理的概述.
有了这些文档,那为什么还说 SEH 贫乏文档呢?其实,Win32 构造化非常处理是操作系统供应的一个服务.你能找到的关于 SEH 的全部文档都是描写特定编译器的运行时库,这个运行库对操作系统实现举行包装._try,_finally 和 _except 这些关键字没有任何奇异的地方.微软的操作系统及其编译器系列定义这些关键字和用法.其他的编译器供应商则只是相沿这些语义.固然借助编译器层的 SEH 可以挽回一些原始操作系统级 SEH 处理不良口碑,但在大众眼里对原始操作系统 SEH 细节的处理感受仍旧.
我收到人们大量的e-mail,都是想要实现编译器级的 SEH 处理,又无法找到操作系统功效供应的相关文档.普通我都是倡议参考 Visual C++ 大概 Borland C++ 运行库源代码.唉,出于一些未知的缘由,编译器级的 SEH 仿佛是一个大的奥秘,微软和 Borland 都不供应其对 SEH 支持的核心层源代码.
在本文中,我将一层一层对 SEH 举行解剖,以便展示其最基本的概念.我打算通过代码产生和运行时库支持将操作系统供应的功效和编译器供应的功效脱离.当我深化代码观察关键的操作系统例程时,我将利用 Intel 平台上的 Windows NT4.0 作为底子.但我将要描写的大大都内容一样实用于别的处理器上运行的利用.
我打算避免触及到真正的 C++ 非常处理,它们利用 catch(),而不是 _except.其实,真正的 C++ 非常处理实现非常近似于本文中描写的内容.但是 C++ 非常处理有一些额外的复杂性会影响我想要触及的概念.
通过深化研究晦涩的 .H 和 .INC 文件来归纳 Win32 SEH 构成,我发现有一个信息源之一就是 IBM OS/2 头文件(特别是 BSEXCPT.H).为此你不要认为大惊小怪..此处描写的 SEH 机制在其源头被定义时,微软仍旧开辟 OS/2 平台(译注: OS/2 平台起先是IBM 和 微软共同研发的,后来因于各种缘由两个公司没有再持续下去).所以你会发现Win32 下的 SEH 和 OS/2 下的 SEH 极端类似.
SEH 浅析
从整体来看,SEH 的可谓盛气凌人,绝对压倒一切,我将从渺小之处开始,用我自己的方法一层一层研究.假如你是一张白纸,从前从没接触过构造化非常处理,那就最好不过了.假如你从前利用过 SEH.那就尝试清理你头脑中的 _try,GetExceptionCode 和 EXCEPTION_EXECUTE_HANDLER 等诸如此类的词,权当自己是个新手.做一个深呼吸,预备好了吗?好,我们开始.
想象一下,我奉告你某个线程出错了,操作系统给你一个机会告诉了这个线程错误,大概再具体一点,当线程出错后,操作系统调用某个用户定义的回调函数.这个回调函数可以所任何它想做的事情.比方,它可以修复任何缘由招致的错误,大概播放一个 .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 中定义以下:
typedef struct _EXCEPTION_RECORD {
DWORD ExceptionCode;
DWORD ExceptionFlags;
struct _EXCEPTION_RECORD *ExceptionRecord;
PVOID ExceptionAddress;
DWORD NumberParameters;
DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD;
ExceptionCode 参数是由操作系统赋值给非常的一个数.你可以在 WINNT.H 文件中搜一下“STATUS_”开始的 #defines 内容便可以得到一系列差别的非常编码.比方 STATUS_ACCESS_VIOLATION 是大家再熟习不过的非常编码了,其值是 0xC0000005.更复杂的非常编码可以从 Windows NT DDK 的 NTSTATUS.H 文件中找到.EXCEPTION_RECORD 构造中的第四个元素是非常发生的地址.剩下的 EXCEPTION_RECORD 域目前可以忽视,不用管它.
_except_handler 回调函数的第二个参数是指向成立者框架(establisher frame)构造的指针,在 SEH 中它是一个至关重要的参数,但目前可以不用关心它.
_except_handler 回调函数的第三个参数是 CONTEXT 构造的指针.CONTEXT 构造在 WINNT.H 中定义,它表示特定线程非常发生时存放器的值:
typedef struct _CONTEXT
{
DWORD ContextFlags;
DWORD Dr0;
DWORD Dr1;
DWORD Dr2;
DWORD Dr3;
DWORD Dr6;
DWORD Dr7;
FLOATING_SAVE_AREA FloatSave;
DWORD SegGs;
DWORD SegFs;
DWORD SegEs;
DWORD SegDs;
DWORD Edi;
DWORD Esi;
DWORD Ebx;
DWORD Edx;
DWORD Ecx;
DWORD Eax;
DWORD Ebp;
DWORD Eip;
DWORD SegCs;
DWORD EFlags;
DWORD Esp;
DWORD SegSs;
} CONTEXT;
以上是“Win32构造化非常处理(SEH)探秘(上)[VC/C++编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |