longjmpで、保存した実行コンテキストの場所に飛び戻ることが出来る。
問題は、setjmpしてからlongjmpするまでに変更された変数の値である。
volatileを付けていない場合は、longjmp後でも、setjmpが呼び出される前の値になっている場合がある。
(未定義だからどちらになるかは不定だが。)
volatileを付けていない変数の参照は未定義になる。
volatileを付けるか、その変数は参照しないこと。
このプログラムでもsetjmp前はxが10、そのあとxを20にしてからlongjmpする。
$ vi longjmp.c $ gcc longjmp.c -o longjmp $ ./longjmp x = 20 x = 20 $
しかし、普通にコンパイルすると、xは20のままで、10にはならない。
実は最適化オプションが影響してくる。
-Oと-O1は同じ。
最適化オプションを付けると、
$ gcc -O longjmp.c -o longjmp $ ./longjmp x = 20 x = 10 $ gcc -O1 longjmp.c -o longjmp $ ./longjmp x = 20 x = 10 $ gcc -O2 longjmp.c -o longjmp $ ./longjmp x = 20 x = 10 $ gcc -O3 longjmp.c -o longjmp $ ./longjmp x = 20 x = 10 $
このように戻ってしまう。
$ gcc longjmp.c -o longjmp $ ./longjmp x = 20 x = 20 $ gcc -O0 longjmp.c -o longjmp $ ./longjmp x = 20 x = 20 $
このような最適化オフだと、保持される。
Sample/c/longjmp/longjmp/src/longjmp at master · bg1bgst333/Sample · GitHub