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