setjmp longjump一些注意点及使用方法
jmp_buf结构体的定义
#define _JBLEN 9
typedef struct { int _jb[_JBLEN + 1]; } jmp_buf[1];
int a()
{
jmp_buf env;
if(setjmp(env) != 0) {exit(0);} //若是异常跳到此,则退出
longjmp(env, 5); //异常跳转,错误码5
}
setjmp(env) 后,env保存的是当前函数a的堆栈地址信息(存在寄存器中)(栈顶指向地址,计数器等),
若此时a没返回,调用了longjmp(env, ret),则寄存器中的数据恢复成env里保存的地址等,相当于程序又退回到setjmp处去运行了
但是栈里的数据还是运行longjmp时的状态,并且会设置setjmp的返回值为ret,此时可以根据ret的值进行switch错误处理(=0是第一次正常运行)。
但是如果是在函数a return后,再调用b函数,b函数内执行longjmp(env, ret),此时是不对的,容易出现段错误。因为env中存的运行时寄存器状态(地址,计数器等)是针对a的栈环境有效,在b函数的栈里可能就是一些无效的值,所以不能这么写。
所以用这2个接口要注意:1.先setjmp再longjmp 2.longjmp的位置必须在setjmp的有效范围内(不能在setjmp所在函数a外,但可以在a里面调用的函数b里)
C++中伪代码
try
xxxx
throw(xx)
xxxx
catch
switch 处理错误码等
end
C里面用setjmp实现类似try catch功能
#include <setjmp.h>
....
jmp_buf env;
switch(setjmp(env)){
case 0:
xxxx
if 出现异常 {longjump(env, 分类处理的错误码);}
xxxx
break;
case 某个错误码:
错误处理
break;
default:
break;
}
....
另:《unix环境高级编程》7.10小节有对这个函数的讲解