C++ プログラミングガイド

terminate()unexpected() 関数の変更

次に、set_terminate()set_unexpected() を使用して terminate() 関数と unexpected() 関数の動きを変更する方法について説明します。

set_terminate()

terminate() のデフォルトの動作は、次のように関数 set_terminate() を呼び出すことによって変更できます。


// 宣言は標準ヘッダー <exception> に含まれる
namespace std {
   typedef void (*terminate_handler)();
   terminate_handler  set_terminate(terminate_handler f) throw();
   void terminate();
}

terminate() 関数は、次のような場合に呼び出されます。

terminate()set_terminate() に引数として渡された関数を呼び出します。このような関数はパラメータを持たず、値を返すこともなく、プログラム (または現在のスレッド) を必ず停止します。set_terminate() への最後の呼び出しで渡された関数が呼び出されます。最後に呼び出された set_terminate() に引数として渡された以前の関数が戻り値になります。そのため terminate を使用し、今までに登録された関数を順次呼び出すようにプログラミングすることができます。terminate() のデフォルトの関数は、メインスレッドに対して abort() を呼び出し、他のスレッドに対して thr_exit() を呼び出します。thr_exit() はスタックを巻き戻したり、自動オブジェクトに対する C++ デストラクタを呼び出すことはありません。


注 -

呼び出し元に戻ったり、プログラムまたはスレッドを終了しないような関数を terminate() の代用として選択すると、エラーになります。


set_unexpected()

unexpected() のデフォルトの動作は、関数 set_unexpected() を呼び出すことによって変更できます。


// 宣言は標準ヘッダー <exception> に含まれる
namespace std {
   class exception;
   class bad_exception;
   typedef void (*unexpected_handler)();
   unexpected_handler
      set_unexpcted(unexpected_handler f) throw();
   void unexpected();
}

unexpected() 関数は、関数がその例外指定にない例外によって終了しようとする場合に呼び出されます。unexpected() のデフォルト版は、terminate() を呼び出します。

ユーザーが変更した unexpected() は、例外指定が許可している例外も送出することがあります。このような場合の例外処理は、その例外が実際に元の関数から送出されたかのように継続します。変更後の unexpected() がそれ以外の例外を送出した場合は、その例外は標準の例外 std::bad_exception に置換されます。元の関数の例外指定が std::bad_exception を許可しない場合は、直後に関数 terminate() が呼び出されます。それ以外では、元の関数が実際に std::bad_exception を送出したかのように例外処理が継続します。

unexpected()set_unexpected() に引数として渡された関数を呼び出します。このような関数は、パラメータを持たず、値を返すこともありません。このような関数はその呼び出し元に戻ってはなりません。set_unexpected() への最後の呼び出しで渡された関数が呼び出されるようになります。以前の set_unexpected() の呼び出し時に引数として渡された関数が戻り値になります。そのため set_unexpected() を使用し、今までに登録された関数を順次呼び出すようにプログラミングすることができます。


注 -

unexpected()の代わりに呼び出し元に戻る関数を選択するとエラーになります。