关于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关键字