zoukankan      html  css  js  c++  java
  • setjump 和 longjump

    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: ");  
    22.          printf("globval = %d, autoval = %d, regival = %d,"  
    23.              " volaval = %d, statval = %d ",  
    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(): ");  
    42.     printf("globval = %d, autoval = %d, regival = %d,"  
    43.         " volaval = %d, statval = %d ", 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  
  • 相关阅读:
    LintCode "Maximum Gap"
    LintCode "Wood Cut"
    LintCode "Expression Evaluation"
    LintCode "Find Peak Element II"
    LintCode "Remove Node in Binary Search Tree"
    LintCode "Delete Digits"
    LintCode "Binary Representation"
    LeetCode "Game of Life"
    LintCode "Coins in a Line"
    LintCode "Word Break"
  • 原文地址:https://www.cnblogs.com/lidabo/p/4500593.html
Copyright © 2011-2022 走看看