longjmp

longjmpで、保存した実行コンテキストの場所に飛び戻ることが出来る。

[法大奥山研究室]C言語:17.2. volatile

問題は、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にはならない。
実は最適化オプションが影響してくる。

g++ 最適化オプション - C++入門

-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