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  
  • 相关阅读:
    可移动的按钮
    .NET及JAVA 中如何使用代码启动程序
    SQL一对多特殊查询,取唯一一条
    jquery,字符串转json对象,json对象转字符串
    jQuery的ajax()、post()方法提交数组,参数[] 问题
    Sql Server中实现Mysql中的group_concat函数效果
    SQL:REGEXP
    sql:CallableStatement执行存储过程
    js去除前后空格
    jsp中常用操作字符串的el表达式
  • 原文地址:https://www.cnblogs.com/lidabo/p/4500593.html
Copyright © 2011-2022 走看看