background image

C 语言中异常处理的两个函数

 

   abort()和 exit()相比,goto 语句看起来是处理异常的更可行方案。不幸的是,goto 是本

地的:它只能跳到所在函数内部的标号上,而不能将控制权转移到所在程序的任意地点

(当然,除非你的所有代码都在 main 体中)。

为了解决这个限制,C 函数库提供了 setjmp()和 longjmp()函数,它们分别承担非局部标号

和 goto 作用。头文件申明了这些函数及同时所需的 jmp_buf 数据类型。

setjmp.h 是 C

标准函数库中提供 非本地跳转 的头文件:控制流偏离了通常的子程序调用

与返回串行。互补的两个函数 setjmp 与 longjmp 提供了这种功能。

setjmp/longjmp 的典型用途是异常处理机制的实现:利用 longjmp 恢复程序或线程的

状态,甚至可以跳过栈中多层的函数调用。

setjmp

 

保存当前的环境(即程序的状态)到平台相关的一个数据结构 (jmp_buf),该

 

数据结构在随后程序执行的某一点可被 longjmp 用于恢复程序的状态到 setjmp 调用所保

存到 jmp_buf 时的原样。这一过程可以认为是"跳转"回 setjmp 所保存的程序执行状态 。

setjmp 的返回值指出控制是正常到达该点还是通过调用 longjmp 恢复到该点。

原理非常简单:

1.setjmp(j)

设置 jump”点,用正确的程序上下文填充 jmp_buf 对象 j。这个上下文包括程序

存放位置、栈和框架指针,其它重要的寄存器和内存数据。当初始化完 jump 的上下文,

setjmp()返回 0 值。

2. 以后调用 longjmp(j,r)的效果就是一个非局部的 goto

或 长跳转 到由 j 描述的上下文处

(也就是到那原来设置 j 的 setjmp()处)。当作为长跳转的目标而被调用时,setjmp()返回 r

或 1(如果 r 设为 0 的话)。(记住,setjmp()不能在这种情况时返回 0。)

jmp_buf 数组类型,例如 struct int[16]或 struct __jmp_buf_tag,用于保存恢复调用环境所需

的信息

通过有两类返回值,setjmp()让你知道它正在被怎么使用。当设置 j 时,setjmp()如你期望

地执行;但当作为长跳转的目标时, setjmp()

就从外面 唤醒 它的上下文。你可以用

longjmp()来终止异常,用 setjmp()标记相应的异常处理程序。

#include

#include