setjmp() — 環境の保存

フォーマット

#include <setjmp.h>
int setjmp(jmp_buf env);

言語レベル

ANSI

スレッド・セーフ

はい

説明

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

setjmp() 関数を呼び出すと、現行スタック環境が、env に保存されることになります。 以後の longjmp() 関数への呼び出しにより、保存済み環境が復元されて、 制御は setjmp() 呼び出しに対応するポイントへ戻されます。 制御を受信する関数に使用可能な (レジスター変数を除いた) すべての変数の値に、 longjmp() 関数の呼び出し時に保持していた値が含まれています。 レジスター変数の値は、予測不可能です。setjmp() 関数と longjmp() 関数の間の呼び出しで変更される、 不揮発性 auto 変数も予測不可能です。

戻り値

setjmp() 関数は、スタック環境を保管してから、0 を戻します。 longjmp() 呼び出しの結果として setjmp() 関数が戻ると、setjmp() 関数は longjmp() 関数の value 引数を戻すか、longjmp() 関数の value 引数が 0 の場合は、1 を戻します。エラーの戻り値はありません。

この例では、下のステートメントで、スタック環境を保存します。
   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()
**********************************************************************/