setjmp和longjmp函数

  关于setjmp函数和longjmp函数有话要说,是UNIX高级环境变成看到了10.10信号那章用到了,研究一下,这里作为补充。

  setjmp(jmp_buf env_buf) 函数可以将当前的运行环境存入jmp_buf变量中,函数默认返回值是返回0。直到longjmp修改该值(!0)后会调回setjmp函数处。

  jmp_buf,是某种形式的数组,其中存放在调用longjmp时能用来恢复栈状态的所有信息。

  那么,当jmp回来后原函数定义的变量是怎样变化的捏??(答案是:不一定)这里又用几个不同类型的变量来看一下。+编译器优化对运行结果产生的影响。

  代码如下:

#include <stdio.h>
#include <setjmp.h>

static jmp_buf jmp_env;

static void f1(int ,int ,int , int );
static void f2(void);

static int globval = 1;


int main(void)
{
    /* 4 kinds variables*/
    int autoval = 2;
    register int regival = 3;
    volatile int volaval = 4;
    static int statval = 5;
    int retval;
    if ( retval = setjmp(jmp_env) ){     /* default value is 0,  so this will run when returns from longjmp()*/
        printf("after longjmp: %d
", retval);  
                 printf("globval=%d,autoval=%d,regival=%d,volaval=%d,statval=%d
",globval,autoval,regival,volaval,statval);  
        //exit(0);
        return 0;  
    }
    /*
     * Change variables's value before calc longjmp.
     */
    globval = 101; autoval = 102; regival = 103; volaval = 104; statval = 105;
    f1(autoval, regival, volaval, statval);
    return 0;
}

static void f1(int i,int j,int k, int l)  
{  
        printf("in f1():
");  
        printf("globval=%d,autoval=%d,regival=%d,volaval=%d,statval=%d
",globval,i,j,k,l);  
        f2();  
}  

static void f2()
{
    printf("in f2():
");
    longjmp(jmp_env, 123);
}

结果如下:

  分析一下:gcc 直接编译没有进行优化,所有变量都会被更改;

       gcc -O  使用编译器优化,其中一种优化包括使用寄存器中的int值来读取,而不是去存储器中读变量。导致这里取到的普通局部变量和寄存器变量是之前的值,并不是更新之后的最新值。

  大多实现并不回滚到这些自动变量和寄存器变量的值,不想使其回滚的话有两种方法:

    1.声明为静态变量static

    2.声明为全局变量

    3.声明为volatile变量(volatile)作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。这是用来防编译器优化的!!!如果要

     编写一个非局部跳转的可移植程序必须要使用volaitle关键字

      

    

原文地址:https://www.cnblogs.com/luntai/p/6171149.html