DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

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点的返回值冲突了)

[cpp] view plaincopy
 
  1. #include "apue.h"  
  2. #include <setjmp.h>  
  3.   
  4. #define TOK_ADD    5  
  5.   
  6. jmp_buf jmpbuffer;  
  7.   
  8. int  
  9. main(void)  
  10. {  
  11.      char    line[MAXLINE];  
  12.   
  13.      if (setjmp(jmpbuffer) != 0)  
  14.          printf("error");  
  15.      while (fgets(line, MAXLINE, stdin) != NULL)  
  16.         do_line(line);  
  17.      exit(0);  
  18. }  
  19.   
  20.  ...  
  21.   
  22. void  
  23. cmd_add(void)  
  24. {  
  25.     int     token;  
  26.   
  27.     token = get_token();  
  28.     if (token < 0)    /* an error has occurred */  
  29.         longjmp(jmpbuffer, 1);  
  30.     /* rest of processing for this command */  
  31. }  


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

[cpp] view plaincopy
 
  1. #include "apue.h"  
  2. #include <setjmp.h>  
  3.   
  4. static void f1(int, int, int, int);  
  5. static void f2(void);  
  6.   
  7. static jmp_buf jmpbuffer;  
  8. static int     globval;  
  9.   
  10. int  
  11. main(void)  
  12. {  
  13.      int             autoval;  
  14.      register int    regival;  
  15.      volatile int    volaval;  
  16.      static int      statval;  
  17.   
  18.      globval = 1; autoval = 2; regival = 3; volaval = 4; statval = 5;  
  19.   
  20.      if (setjmp(jmpbuffer) != 0) {  
  21.          printf("after longjmp:\n");  
  22.          printf("globval = %d, autoval = %d, regival = %d,"  
  23.              " volaval = %d, statval = %d\n",  
  24.              globval, autoval, regival, volaval, statval);  
  25.          exit(0);  
  26.      }  
  27.   
  28.      /* 
  29.       * Change variables after setjmp, but before longjmp. 
  30.       */  
  31.      globval = 95; autoval = 96; regival = 97; volaval = 98;  
  32.      statval = 99;  
  33.   
  34.      f1(autoval, regival, volaval, statval); /* never returns */  
  35.      exit(0);  
  36. }  
  37.   
  38. static void  
  39. f1(int i, int j, int k, int l)  
  40. {  
  41.     printf("in f1():\n");  
  42.     printf("globval = %d, autoval = %d, regival = %d,"  
  43.         " volaval = %d, statval = %d\n", globval, i, j, k, l);  
  44.     f2();  
  45. }  
  46. static void  
  47. f2(void)  
  48. {  
  49.     longjmp(jmpbuffer, 1);  
  50. }  
[cpp] view plaincopy
 
    1. $ cc testjmp.c               compile without any optimization  
    2. $ ./a.out  
    3. in f1():  
    4. globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99  
    5. after longjmp:  
    6. globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99  
    7. $ cc -O testjmp.c            compile with full optimization  
    8. $ ./a.out  
    9. in f1():  
    10. globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99  
    11. after longjmp:  
    12. globval = 95, autoval = 2, regival = 3, volaval = 98, statval = 99  
posted on 2015-05-13 15:32  DoubleLi  阅读(1281)  评论(0编辑  收藏  举报