非本地跳转函数setjmp和longjmp
来源:     阅读:747
云上智慧
发布于 2020-04-24 19:25
查看主页

C语言提供了一种客户级的异常控制流形式,称为非本地跳转(nonlocal jump),它可以将控制流直接从一个函数转移到另一个当前正在执行的函数,而不需要经过正常的调用和返回序列。而这些都是通过两组函数实现的。

setjmp函数

首先来看看函数原型:

#include <setjmp.h>int setjmp(jmp_buf env);                        //返回0int sigsetjmp(sigjmp_buf env, int savesigs);    //返回0               

longjmp函数

首先来看看函数原型:

#include <setjmp.h>void longjmp(jmp_buf env, int retval);      //从不返回void siglongjmp(jmp_buf env, int retval);   //从不返回

应用

1. 从深层嵌套中立即返回

他的意思有点向C语言中的go语句。当程序执行到深层嵌套中的某个函数时,假如此时监测到了一个错误,我们可以利用setjmp和longjmp的组合,直接从最里层返回到上层的错误解决程序,而不需要繁琐的一层层解开调用栈。

下面展现的例子,说明了上述情况。main函数首先调用setjmp函数保存当前的调用环境,而后再调用函数foo,foo依次调用bar。假如任一函数遇到错误,它们立即通过longjmp调用从setjmp返回。而我们可以通过setjmp的不同非零返回值知道错误类型,然后进入相应的解错程序。

#include <setjmp.h>jmp_buf buf;/*此处我们假设程序可能有两个错误,其中error2会发生;*/int error1 = 0;     int error2 = 1;void foo(void),bar(void);   //公告两个函数int main(void){    switch(setjmp(buf)){        case 0:            foo();            break;        case 1:            printf("Detected error1 in foo.\n");            break;        case 2:            printf("Detected error2 in bar.\n");            break;        default:            printf("Unknown error in foo.\n");               }    exit(0);}void foo(void){    if(error1)        longjmp(buf, 1);    bar();}void bar(void){    if(error2)        longjmp(buf, 2);}

但在使用这种非本地跳转时要避免跳过的中间过程不会产生反作用;例如,假如我们在foo函数中调用了malloc函数分配了少量内存空间,原本估计在函数结尾处回收它们。但偏偏又在调用bar函数的过程中发生了错误,导致了bar函数直接返回到了最上层,这样就会发生内存泄漏。

2. 使信号解决分支到达特定位置,而非返回到被中断的指令处

下面展现了一个尽管被要求终止,但却可以自我重启的程序。程序第一次启动时,对sigsetjmp函数的调用保存了调用环境和信号上下文(待解决的信号位向量pending和被阻塞的信号位向量blocked)。随后,主函数进入无限循环。当客户键入Ctrl + C时,内核向程序发送SIGINT信号,进程捕获后执行我们自己设置的信号解决程序,该程序调用siglongjmp函数使得程序跳转到sigsetjmp处返回retval。主程序得以重新开始。

#include <signal.h>sigjmp_buf buf;void handler(int sig){    siglongjmp(buf, 1);}int main(void){    if(!sigsetjmp(buf, 1)){        Signal(SIGINT, handler);        Unix_exit("starting\n");    }    else        Unix_exit("restarting\n");        while(1){        sleep(1);        Unix_exit("processing...\n");    }    exit(0);}

获取更多知识,请点击关注:
嵌入式Linux&ARM
CSDN博客
简书博客


免责声明:本文为用户发表,不代表网站立场,仅供参考,不构成引导等用途。 系统环境 服务器应用
相关推荐
??性能强悍的 TS 版 G6 来了,给您拜个早年??
大话<数据传输安全与加密>
你们要的短视频源码来了!功能分析实战——短视频开发功能解读篇
不懂SQL优化?那你就OUT了——order by
前台高效开发必备的 js 库梳理
首页
搜索
订单
购物车
我的