longjmp() — スタック環境の復元

フォーマット

#include <setjmp.h>
void longjmp(jmp_buf env, int value);

言語レベル

ANSI

スレッド・セーフ

はい

説明

longjmp() 関数は、以前 setjmp() 関数によって env に保管されているスタック環境を復元します。 setjmp() および longjmp() 関数は、非ローカル goto を実行する方法を提供します。 これらは、シグナル・ハンドラーでよく使用されます。

setjmp() 関数の呼び出しにより、現行スタック環境が env に保管されます。 次に longjmp() を呼び出すと、保管した環境が復元され、setjmp() 呼び出しに対応するプログラム内のポイントへ制御が戻されます。 setjmp() 呼び出しによって、指定 value が戻された時点から処理が再開されます。

制御を受け取る関数で使用可能なすべての変数 (register 変数を除く) には、longjmp() が呼び出されたときに設定されていた値が入ります。 レジスター変数の値は、予測不可能です。setjmp() および longjmp() 関数の間の呼び出しで変更される、不揮発性 auto 変数も予測不可能です。
注: setjmp() を呼び出す関数が、対応する longjmp() 関数を呼び出す前に戻らないことを確認してください。 setjmp() を呼び出す関数が戻った後に longjmp() を呼び出すと、予測不可能なプログラムの振る舞いを引き起こします。

引数 value は非ゼロでなければなりません。 ゼロ引数を value に指定すると、longjmp() により 1 に置換されます。

戻り値

longjmp() 関数は、普通の関数呼び出しや戻りメカニズムを使用しません。したがって、戻り値はありません。

この例では、下のステートメントで、スタック環境を保存します。
   if (setjmp(mark) != 0) ...
システムは、最初に if ステートメントを実行する場合、 環境を mark に保管し、条件を FALSE に設定します。 これは、setjmp() 関数が環境を保管するとき 0 を戻すためです。 プログラムで次のメッセージが出力されます。
   setjmp has been called

関数 p() への以降の呼び出しで、longjmp() 関数が呼び出されます。 制御は、mark 変数内に保存された環境を使用して、setjmp() 関数への呼び出しの直後に main() 関数内のポイントに渡されます。この場合、条件は TRUE ですが、これは戻り値がスタック上に置かれるよう、longjmp() 関数呼び出しの 2 番目のパラメーターで -1 が指定されているためです。 次に、この例ではブロック中のステートメントが実行され、"longjmp() has been called" というメッセージが出力されます。その後、recover() 関数が実行され、プログラムが終了します。

#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
 
jmp_buf mark;
 
void p(void);
void recover(void);
 
int main(void)
{
   if (setjmp(mark) != 0)
   {
      printf("longjmp has been called¥n");
      recover();
      exit(1);
      }
   printf("setjmp has been called¥n");
   printf("Calling function p()¥n");
   p();
   printf("This point should never be reached¥n");
}
 
void p(void)
{
   printf("Calling longjmp() from inside function p()¥n");
   longjmp(mark, -1);
   printf("This point should never be reached¥n");
}
 
void recover(void)
{
   printf("Performing function recover()¥n");
}
/*******************Output should be as follows: **********************
 setjmp has been called
 Calling function p()
 Calling longjmp() from inside function p()
 longjmp has been called
 Performing function recover()
**********************************************************************/