setjmp/longjmp

    该 API 的作用与 goto 类似,但 goto 是本地的,只能跳转到函数内部的标记上,而不能将控制权转移到程序的任何地点。

    C 语言为了解决该限制,提供了 setjmp 和 longjmp。声明在 setjmp.h 头文件中,且包含了 jmp_buf 的声明。原理是:

1. setjmp(jmp_buf buf) 设置 jump 点,向 buf 中填充程序存放位置、栈、寄存器等数据。填充完毕后,setjmp 返回 0;

2. 以后调用 longjmp(buf, return),其效果就是一个非局部的 goto,即跳转到设定 buf 的 setjmp 处。当作为长跳转的目标而被调用时,setjmp 返回 return 值或者 1(如果此时 return 被设置成 0,则返回 1,即,此时 setjmp 不能返回 0).

    事实上,setjmp/longjmp 更像是 come from,即从哪里来,而不是 goto,即到哪里去。

    setjmp/longjmp 在 C++ 中变异为更普通的 catch/throw 异常处理机制。

    setjmp/longjmp 是通过操纵“过程活动记录”实现的。关于“过程活动记录”及 setjmp/longjmp 的实现原理,尚待进一步研究。

    man setjmp 中提到:

    setjmp() saves the stack context/environment in buf for later use by longjmp().The stack context will be invalidated if thefunction which called setjmp() returns.

    所以,对 setjmp 的调用不能额外的再封装一层函数,例如:

    int try(breakpoint bp) {

        return setjmp(bp->jb);

    }

    此时,尽管编译不会受到影响,但是会引起运行错误。

    回想“过程活动记录”,记录的是函数返回地址、参数等信息,如果在 setjmp() 外面再包一层,那么记录的函数地址就不是想跳转的函数了。

    Code Sample:

    #include <setjmp.h>

    jmp_buf buf;

    void test(void) {

        printf("in test()\r\n");

        longjmp(buf, 1);

        printf("u'll never c this\r\n");

    }

    int main(int argc, char *argv[]) {

        /* 第一次调用返回 0,执行 else 分支;longjmp 调用后,跳转到此处,返回 longjmp 中设定的 1,于是打印 "back in main" */

        if (setjmp(buf)) {

            printf("back in main\r\n");

        } else {

            printf("first time\r\n");

            test();

        }

    }


PS:去了解一下 C++ 的 RAII

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值