浅谈 Win32 系统级 S.E.H
在 Win32 操作系统提供的所有系统级特性中,S.E.H(Structrued Exception
Handling)结构化异常处理机制或许是最为广泛使用同时又是最没有被文档公开的技术之
一(还有其它一些特性例如 Win32 的系统级堆管理机制也是如此)。当提及 Win32 的异
常处理机制时,你可能首先想到的可能是像_try,_nally,或者是_except 这些关键字。
有许多跟 Win32 编程相关的书籍都有对 SEH 的描述,那为什么说 SEH 其实是并没有
公开化的,或者为什么说至今并没有官文的文档来详细描述?Win32 S.E.H 是系统提供的
一种服务。然而我们所能够找到的关于 S.E.H 的资料几乎者是在某个特定编译器下的 SEH
使用方法。_try,_nally,_except 并没有什么神奇之处,因为 MS 已经公开出他们对这些
关键字的功能定义及其用法。其它的一些 C++编译生产商(比如 Borland)也是简单地跟
着 MS 的定义走,然而这些编译器生产商也都并没有公开他们的编译器级的源代码。当把
各个软件商把编译器级的 SEH 封装在系统级的 SEH 上,众多的用户越来越受到其便利性
的时候,系统级 SEH 具体细节也就慢慢从人们的视野中淡去。
在这文章中,将尝试说明 SEH 设计之初的一些最基本的需求。
初识 S.E.H
如果一下子把 SEH 所有细节都提出来,大家肯定会一下子接受不来。因此,打算一个
小方面入手,并循序渐进。如果你从来就没有正经使用过 Win32 的异常处理机制,那刚刚
好,因为你不会有先入为主的倾向。如果你已经使用过 SEH,尝试着先摒弃一些诸如异常处
理就是_try,GetExceptionCode ···的想法,假装这些对你来说都是新的。好的,让我们
正式开始。
设想,当一个线程发生错误时,OS 会给你一个机会让你知道哪里哪个时候发生了什
么错误,同时也让你在这个时候去补救这个错误。用行话说,当一个线程发生错误的时候
OS 会调用一个用户自定义的回调函数(CallBack),而这个函数能够做任何事情(不管里
面是否真的是不是在处理异常)。比如说,这个函数可以用来处理这个错误,也可以让它
放一首歌放一段 AVI。这个函数同时得返回一个值给 OS,以告诉 OS 自己有没有处理好这
个错误异常,不然 OS 怎么知道这个异常有没有被解决哦!
那么当一个异常发生的时候,为了处理异常,你希望获得哪些东西呢?那就无外乎发
生异常时代码的地址,发生异常时的堆栈情况,以及当时寄存器组的信息。如果要你为定
义这个回调函数的原型,你会如何设置参数呢?Win32 OS 正是基于这种思路而定义了标
准的回调函数的函数原型: