longjmp對自動,寄存器,全局變量,靜態(tài)變量,和易失變量(Volatile Variable)的影響
 
當longjmp返回到main函數(shù)時,這些變量的值是否能恢復到以前調用setjmp時的值(即滾回原先值),或者這些
變量的值保持為最新的值?不幸的是,對此問題的回答是“看情況”。大多數(shù)實現(xiàn)并不滾回這些自動變量和寄存器變量的值,而所有標準則說它們的值是不確定的。如果你有一個自動變量,而又不想使其值滾回,則可定義其為具有volatile屬性。說明為全局和靜態(tài)變量的值在執(zhí)行l(wèi)ongjmp時保持不變。
一下是APUE中的例子:
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
static void f1(int, int, int, int);
//static void f2(void);
static jmp_buf jmpbuffer;
static int globval;
int main(void)
{
     int autoval;
     register int regival;
     volatile int volaval;
     static int statval;
     globval = 1; autoval = 2; regival = 3; volaval = 4; statval = 5;
     if (setjmp(jmpbuffer) != 0) {
         printf("after longjmp:/n");
         printf("globval = %d, autoval = %d, regival = %d,"
             " volaval = %d, statval = %d/n",
             globval, autoval, regival, volaval, statval);
         exit(0);
     }
     /*
      * Change variables after setjmp, but before longjmp.
      */
     globval = 95; autoval = 96; regival = 97; volaval = 98;
     statval = 99;
     f1(autoval, regival, volaval, statval); /* never returns */
     exit(0);
}
static void f1(int i, int j, int k, int l)
{
    printf("in f1():/n");
    printf("globval = %d, autoval = %d, regival = %d,"
        " volaval = %d, statval = %d/n", globval, i, j, k, l);
        
    //f2();
    longjmp(jmpbuffer, 1);
}
static void f2(void)
{
    longjmp(jmpbuffer, 1);
}
如果以不帶優(yōu)化和帶優(yōu)化選項對此程序分別進行編譯,然后運行它們,則得到不同的結果: 
$ cc testjmp.c               compile without any optimization
    $ ./a.out
    in f1():
    globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
    after longjmp:
    globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
    
$ cc -O testjmp.c            compile with full optimization
    $ ./a.out
    in f1():
    globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
    after longjmp:
    globval = 95, autoval = 2, regival = 3, volaval = 98, statval = 99
注意,易失變量(sum)不受優(yōu)化的影響,在longjmp之后的值,是它在調用f1時的值。在我們所使用的setjmp(3)手冊頁上說明存放在存儲器中的變量將具有l(wèi)ongjmp時的值,而在CPU和浮點寄存器中的變量則恢復為調用setjmp時的值。這確實就是在運行以上程序時所觀察到的值。不進行優(yōu)化時,所有這三個變量都存放在存儲器中(亦即對val的寄存器存儲類被忽略)。而進行優(yōu)化時,count和val都存放在寄存器中(即使count并末說明為register),volatile變量則仍存放在存儲器中。通過這一例子要理解的是,如果要編寫一個使用非局部跳轉的可移植程序,則必須使用volatile屬性。