【原创】setjmp longjump一些注意点及使用方法

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小节有对这个函数的讲解

posted @ 2015-03-06 16:29  vanishfan  阅读(1284)  评论(0编辑  收藏  举报