C++ で longjmp() 関数を使ってはならない
longjmp()
関数を使うと C でも例外処理っぽいことができるわけだが、これは、間違っても C++ プログラム中では使ってはならない。まあ、C++ には本物の例外処理があるので使うわけもないのだが、C との混合プログラミング*1の際などには注意を要する。
問題は、longjmp()
の呼び出しによって消滅するスタック上のオブジェクトのデストラクタが呼ばれない、ということだ。例外送出に伴うスタック巻き戻しではスタック上のオブジェクトが解体されるが、longjmp()
にはこれがない。いや、デストラクタが呼び出されないどころか、そもそもそういう事態での C++ プログラムの挙動は不定である:
- C++ 標準*2 ― 18.7 の 4
-
The function signature
longjmp(jmp_buf jbuf, int val)
has more restricted behavior in this International Standard. If any automatic objects would be destroyed by a thrown exception transferring control to another (destination) point in the program, then a call tolongjmp(jbuf, val)
at the throw point that transfers control to the same (destination) point has undefined behavior.
longjmp()
の呼び出しの結果として消滅するスタックにデストラクタが呼び出されるような*3オブジェクトがあったら、プログラムの動作がどうなるかは分からないよ」ということだ。「undefined behavior」なので、それこそ、HDD をフォーマットされても文句は言えない。現実問題として C++ で RAII を意識しないプログラミングはありえず、したがって、
longjmp()
関数の出る幕はない。自己矛盾もいいところの <csetjmp>
なんていうヘッダは、間違っても include
してはならない。