namespace std {
[[noreturn]] void longjmp(jmp_buf env, int val);
}
概要
引数envに保存された実行環境を復元し、対応するsetjmp()の呼び出し地点へプログラムの制御を移す(非ローカルジャンプ)。
効果
setjmp()によって第一引数envに保存された実行環境(スタックポインタ、プログラムカウンタ等)を復元する。- プログラムの実行地点を、対応する
setjmp()の呼び出し地点へジャンプさせる。 - ジャンプ先の
setjmp()は、この関数の第二引数valを戻り値として返す。ただし、valが0の場合は1を返す。
戻り値
この関数は決して返らない。
備考
以下の場合、動作は未定義である。
- 対応する
setjmpとlongjmpをcatchとthrowに置き換えたときに、自動記憶域期間を持つオブジェクトのデストラクタが関係する場合- C++98 : そのオブジェクトが破棄される場合。デストラクタがトリビアルであるかどうかは問わない
- C++11 : そのオブジェクトの非トリビアルなデストラクタが呼び出される場合。例えば、
setjmpとlongjmpの間で、非トリビアルなデストラクタを持つオブジェクトの生存期間が開始し、終了しない場合(ジャンプによってデストラクタを飛ばす場合)
- C++20 : コルーチンのサスペンションコンテキスト (
co_await式の評価中) で呼び出された場合 - 対応する
setjmpが存在しない場合(envが有効な環境を保存していない場合) longjmpは、対応するsetjmpの呼び出しから同一スレッド内で呼び出されなければならない。異なるスレッドから呼び出された場合setjmpを呼び出した関数の実行が終了している場合
また、volatile修飾子のついていないsetjmpを呼び出した関数に対してローカルな変数で、その値がsetjmpからlongjmpの呼び出しの間で変更されたものがある場合、その変数の値は不定となる。
例
#include <iostream>
#include <csetjmp>
std::jmp_buf env;
void inner_function() {
std::cout << "何らかのエラー" << std::endl;
std::longjmp(env, 0); // valが0なので、setjmpは1を返す
}
int main () {
if (setjmp(env) == 0) {
inner_function();
} else {
std::cout << "エラーから復帰しました" << std::endl;
}
return 0;
}
出力
何らかのエラー
エラーから復帰しました
関連項目
参照
- LWG Issue 894.
longjmpand destructors- C++11で、動作は未定義となる条件が「自動記憶域期間のオブジェクトを破棄する場合」から「非トリビアルなデストラクタを呼び出す場合」に限定された。トリビアルなデストラクタしか持たないオブジェクトを飛び越えるだけであれば、実際には問題が起きず、既存の実装もそのような使い方を許していたため
- P0912R5 Merge Coroutines TS into C++20 working draft
- C++20で、コルーチンのサスペンションコンテキストでこの関数を呼び出した場合の動作は未定義であることが規定された