编译器如何实现异常处理.pdf

C 编译器如何实现异常处理 C++编译器如何实现异常处理 转自:原文出处: How aC++compiler implements exception handling 译者注: 本文在网上已经有几个译本,但都不完整,所以我决定自己把它翻译过来。虽然力 求信、雅、达,但鉴于这是我的第一次翻译经历,不足之处敬请谅解并指出。与传 统语言相比, C++的一项革命性创新就是它支持异常处理。传统的错误处理方式经 常满足不了要求,而异常处理则是一个极好的替代解决方案。它将正常代码和错误 处理代码清晰的划分开来,程序变得非常干净并且容易维护。本文讨论了编译器如 何实现异常处理。我将假定你已经熟悉异常处理的语法和机制。本文还提供了一个 用于 VC++的异常处理库,要用库中的处理程序替换掉 VC++提供的那个,你只需要 调用下面这个函数: install_my_handler() ;之后,程序中的所有异常,从它们被抛出到堆栈展开 (stack unwinding) ,再到调用 catch 块,最后到程序恢复正常运行,都将由我的 异常处理库来管理。与其它 C++特性一样, C++标准并没有规定编译器应该如何来 实现异常处理。这意味着每一个编译器的提供商都可以用它们认为恰当的方式来实 现它。下面我会描述一下 VC++是怎么做的,但即使你使用其它的编译器或操作系 统①,本文也应该会是一篇很好的学习材料。 VC++的实现方式是以 windows 系统的 结构化异常处理 (SEH)②为基础的。结构化异常处理 - 概述在本文的讨论中,我认为 异常或者是被明确的抛出的,或者是由于除零溢出、空指针访问等引起的。当它发 生时会产生一个中断,接下来控制权就会传递到操作系统的手中。操作系统将调用 异常处理程序,检查从异常发生位置开始的函数调用序列,进行堆栈展开和控制权 转移。 Windows定义了结构 EXCEPTION_REGISTRATION,使我们能够向操作系统注 册自己的异常处理程序。 struct EXCEPTION_REGISTRATION EXCEPTION_REGISTRATION*prev; DWORD handler; } ;注册时,只需要创建这样一个结构,然后把它的地址放到 FS段偏移 0 的位置上 去就行了。下面这句汇编代码演示了这一操作: mov FS:[0],exc_regp prev 字段用于建立一个 EXCEPTION_REGISTRATION结构的 链表,每次注册新的 EXCEPTION_REGISTRATION时,我们都要把原来注册的那个的 地址存到 prev 中。那么,那个异常回调函数长什么样呢 ?在 excpt.h 中,windows 定义了它的原形: EXCEPTION_DISPOSITION(*handler)( _EXCEPTION_RECORD*ExcRecord, void*EstablisherFrame, _CONTEXT*ContextRecord, void*DispatcherContext) ;不要管它的参数和返回值,我们先来看一个简单的例 子。下面的程序注册了一个异常处理程序,然后通过除以零产生了一个异常。异常 处理程序捕获了它,打印了一条消息就完事大吉并退出了。 #include iostream #include windows.h using std :cout ; using std :endl ; struct EXCEPTION_REGISTRATION EXCEPTION_REGISTRATION*prev; DWORD handler; } ; EXCEPTION_DISPOSITION myHandler( _EXCEPTION_RECORD*ExcRecord, void*EstablisherFrame, _CONTEXT*ContextRecord, void*DispatcherContext) coutIn the exception handlerendl ; coutJust ademo.exiting.endl ; exit(0)

文档评论(0)

1亿VIP精品文档

相关文档