setjump 和 longjump

来源:互联网 发布:seo蜘蛛精 编辑:程序博客网 时间:2024/06/06 20:59

    goto语句可以用于同一个函数内异常处理,不幸的是,goto是本地的,它只能跳到所在函数内部的标号上。为了解决这个限制,C函数库提供了setjmp()和longjmp()函数,它们分别承担非局部标号和goto作用。头文件<setjmp.h>申明了这些函数及同时所需的jmp_buf数据类型。
    1.setjmp(jbuf)设置“jump”点,用正确的程序上下文填充jmp_buf对象jbuf。这个上下文包括程序存放位置、栈和框架指针,其它重要的寄存器和内存数据。当初始化完jump的上下文,setjmp()返回0值。
    2. 以后调用longjmp(jbuf,r)的效果就是一个非局部的goto或“长跳转”到由jbuf描述的上下文处(也就是到那原来设置jbuf的setjmp()处)。当作为长跳转的目标而被调用时,setjmp()返回r (或1,如果r设为0的话)。(setjmp()不能在这种情况时返回0,否则就和设置jump点的返回值冲突了)

#include "apue.h"#include <setjmp.h>#define TOK_ADD    5jmp_buf jmpbuffer;intmain(void){     char    line[MAXLINE];     if (setjmp(jmpbuffer) != 0)         printf("error");     while (fgets(line, MAXLINE, stdin) != NULL)        do_line(line);     exit(0);} ...voidcmd_add(void){    int     token;    token = get_token();    if (token < 0)    /* an error has occurred */        longjmp(jmpbuffer, 1);    /* rest of processing for this command */}


setjump和longjump返回时对auto变量、register变量、volatile变量和静态变量的恢复情况示例。cc -O选项表示编译优化。
longjump返回时一般情况下不会恢复到setjump时的值,此种情况属于未定义。
如果你不想让anto变量的值回滚,需要加上volatile属性。

#include "apue.h"#include <setjmp.h>static void f1(int, int, int, int);static void f2(void);static jmp_buf jmpbuffer;static int     globval;intmain(void){     int             autoval;     register int    regival;     volatile int    volaval;     static int      statval;     globval = 1; autoval = 2; regival = 3; volaval = 4; statval = 5;     if (setjmp(jmpbuffer) != 0) {         printf("after longjmp:\n");         printf("globval = %d, autoval = %d, regival = %d,"             " volaval = %d, statval = %d\n",             globval, autoval, regival, volaval, statval);         exit(0);     }     /*      * Change variables after setjmp, but before longjmp.      */     globval = 95; autoval = 96; regival = 97; volaval = 98;     statval = 99;     f1(autoval, regival, volaval, statval); /* never returns */     exit(0);}static voidf1(int i, int j, int k, int l){    printf("in f1():\n");    printf("globval = %d, autoval = %d, regival = %d,"        " volaval = %d, statval = %d\n", globval, i, j, k, l);    f2();}static voidf2(void){    longjmp(jmpbuffer, 1);}
    $ cc testjmp.c               compile without any optimization    $ ./a.out    in f1():    globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99    after longjmp:    globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99    $ cc -O testjmp.c            compile with full optimization    $ ./a.out    in f1():    globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99    after longjmp:    globval = 95, autoval = 2, regival = 3, volaval = 98, statval = 99


 

0 0
原创粉丝点击