Win32结构化异常处理(SEH)探秘(上)
凡响。如果你慢慢研究,其实并没有那么糟。例如,忽略返回类型(EXCEPTION_DISPOSITION)。基本上你看到的就是一个叫做 _except_handler 的函数,这个函数带有四个参数。
第一个参数是指向 EXCEPTION_RECORD 结构指针,该结构在 WINNT.H 中定义如下: typedef struct _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 中定义,它表示特定线程异常发生时寄存器的值:
此外,这个 CONTEXT 结构与 GetThreadContext 和 SetThreadContext API 函数使用的结构是相同的。 _except_handler 回调函数的第四个参数是 DispatcherContext。现在也可以忽略它。 为了简化起见,当异常发生时,你有一个回调函数被调用。此回调函数带四个参数,其中三个是结构指针。在这些结构中,某些域是很重要的,其余的不是那么重要。关键是 _except_handler 回调函数接收 很多信息,比如发生了什么类型的异常,在哪里发生的。利用这些信息,异常回调机制需要确定要做什么。 虽然我迫不急但地想抛出例子程序示范 _except_handler 回调的运行,但还有一些事情不能漏掉,需要说明。特别是当错误发生时,操作系统如何知道到哪里调用?答案仍然涉及另外一个结构 EXCEPTION_REGISTRATION。你将自始自终在本文中看到这个结构,所以不要掠过这部分内容。我能找到正式定义 EXCEPTION_REGISTRATION 结构的唯一地方是 EXSUP.INC 文件,该文件来自 Visual C++ 运行库的源:
你还将看到该结构在 WINNT.H 文件中定义的 NT_TIB 结构中被引用为 _EXCEPTION_REGISTRATION_RECORD。唉,除此之外,没有什么地方能找到 _EXCEPTION_REGISTRATION_RECORD 的定义,所以我只能使用 EXSUP.INC 文件中定义的汇编语言结构。这也是我为什么在本文前述内容中说过的 SEH 缺乏文档的一个例证。 不管怎样,让我们回到手头的问题,当某个异常发生时,OS 如何知道到哪里调用回调函数?EXCEPTION_REGISTRATION 由两个域构成,第一个你现在可以忽略。第二个域是句柄,它包含 _except_handler 回调函数的指针。这让你更接近一点了,但目前问题来了,OS 在哪里查找并发现 EXCEPTION_REGISTRATION 结构? 为了回答这个问题 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |