signal(C RTL)
signal.h:インデックス への移動
ヘッダーファイル
signal.h
カテゴリ
プロセス制御ルーチン
プロトタイプ
void (_USERENTRY *signal(int sig, void (_USERENTRY *func)(int sig[, int subcode])))(int);
説明
シグナル処理アクションを指定します。
signal は,シグナル番号 sig が受け取った後で,それをどのように処理するかを決定します。ユーザー指定のハンドラルーチン(引数 func で指定される)をインストールするか,signal.h で定義されているハンドラ SIG_DFL および SIG_IGN のいずれかを使用します。関数 func は,_USERENTRY 呼び出し規約を使って宣言する必要があります。
シグナル(浮動小数点など)を捕捉するルーチンは,シグナルのクリアも行います。続けてシグナルを受信するには,再度 signal を呼び出して,シグナルハンドラを再インストールする必要があります。
SIG_DFL |
プログラムを終了します。 |
SIG_ERR |
シグナルからエラーが返されたことを示します。 |
SIG_IGN |
この型のシグナルを無視します。 |
次の表に,シグナルの型とそれらのデフォルトの動作を示します。
SIGBREAK |
キーボードがローモードである必要があります。 |
SIGABRT |
異常終了。デフォルトのアクションは,_exit(3) の呼び出しと同じです。 |
SIGFPE |
ゼロ除算演算エラー,無効な操作など。デフォルトのアクションは,_exit(1) の呼び出しと同じです。 |
SIGILL |
不正な操作。デフォルトのアクションは,_exit(1) の呼び出しと同じです。 |
SIGINT |
Ctrl-C 割り込み。デフォルトのアクションは,_exit(3) の呼び出しと同じです。 |
SIGSEGV |
ストレージへの不正なアクセス。デフォルトのアクションは,_exit(1) の呼び出しと同じです。 |
SIGTERM |
プログラムの終了の要求。デフォルトのアクションは,_exit(1) の呼び出しと同じです。 |
ユーザー定義シグナルは,raise の呼び出しによってのみ生成されます。デフォルトのアクションはシグナルを無視することです。 |
signal.h には,sig_atomic_t という型が定義されています。これは,非同期割り込みが存在するときに,プロセッサがアトミックにロードまたは保存できる最大の整数の型です(32 ビットの整数 -- Borland C++ 整数)。
raise 関数または外部イベントによってシグナルが生成されると,次の 2 つの動作が行われます。
- そのシグナルに対するユーザー指定のハンドラがインストールされている場合は,そのシグナルの型に対するアクションが SIG_DFL に設定されます。
- そのシグナルの型をパラメータとして使用して,ユーザー指定の関数が呼び出されます。
ユーザー指定のハンドラ関数は,return で終了するか,abort,_exit,exit,または longjmp を呼び出して終了できます。ハンドラ関数によってさらにシグナルを受信して処理できるようにするには,ハンドラ関数から再度 signal を呼び出す必要があります。
Borland C++ は,シグナルの型が SIGFPE,SIGSEGV,または SIGILL の場合に,ANSI C の拡張機能を実装しています。ユーザー指定のハンドラ関数は,1 つまたは 2 つの追加パラメータを付けて呼び出すことができます。raise 関数の明示的な呼び出しによって SIGFPE,SIGSEGV,または SIGILL が生成された場合は,ユーザー指定のハンドラが 1 つの追加パラメータを付けて呼び出されます。このパラメータは,明示的に呼び出されるハンドラを指定する整数です。SIGFPE,SIGSEGV,および SIGILL に対する明示的なアクティブ化の値は次のとおりです。
メモ: これらの型の宣言は,float.h で定義されています。
SIGFPE |
FPE_EXPLICITGEN |
SIGSEGV |
SEGV_EXPLICITGEN |
SIGILL |
ILL_EXPLICITGEN |
浮動小数点例外によって SIGFPE が生成された場合は,シグナルの FPE_xxx 型を指定する追加パラメータを付けてユーザーハンドラが呼び出されます。プロセッサ例外の結果として SIGSEGV,SIGILL,または整数関連の SIGFPE シグナル(FPE_INTOVFLOW または FPE_INTDIV0)が生成された場合は,2 つの追加パラメータを付けてユーザーハンドラが呼び出されます。
1. SIGFPE,SIGSEGV,または SIGILL 例外型(これらの型については,float.h を参照)。最初のパラメータは,通常の ANSI シグナル型です。
2. ユーザー指定のハンドラを呼び出した割り込みハンドラのスタックへの整数ポインタ。このポインタは,例外の発生時に保存されたプロセッサレジスタのリストを指します。レジスタは,割り込み関数のパラメータと同じ順序(EBP,EDI,ESI,EDS,ES,EDX,ECX,EBX,EAX,EIP,CS,EFL)です。ハンドラから返るときにレジスタ値を変更するには,このリスト内の位置の 1 つを変更します。
たとえば,新しい SI 値を返すには,次のようにします。
*((int*)list_pointer + 2) = new_SI_value;
このように,ハンドラで任意のレジスタを調べたり,調整することができます。
次の SIGFPE 型のシグナルが発生(または生成)する可能性があります。これらは,80x87 ファミリーが検出可能な例外と,メイン CPU の「INTEGER DIVIDE BY ZERO」および「INTERRUPT ON OVERFLOW」に対応します。これらの宣言は float.h にあります。
FPE_INTOVFLOW |
OF フラグを設定した INTO の実行 |
FPE_INTDIV0 |
ゼロによる整数の除算 |
FPE_INVALID |
無効な操作 |
FPE_ZERODIVIDE |
ゼロによる除算 |
FPE_OVERFLOW |
数値オーバーフロー |
FPE_UNDERFLOW |
数値アンダーフロー |
FPE_INEXACT |
精度 |
FPE_EXPLICITGEN |
ユーザープログラムによる raise(SIGFPE) の実行 |
FPE_STACKFAULT |
浮動小数点のスタックオーバーフローまたはアンダーフロー |
FPE_STACKFAULT |
スタックオーバーフロー |
FPE_INTOVFLOW および FPE_INTDIV0 シグナルは整数演算によって生成され,その他は浮動小数点演算によって生成されます。浮動小数点例外が生成されるかどうかは,コプロセッサコントロールワードに依存します。これは,_control87 で変更できます。非正規化例外は,Borland C++ によって処理され,シグナルハンドラには渡されません。
次の SIGSEGV 型のシグナルが発生する可能性があります。
SEGV_BOUND |
範囲制約例外 |
SEGV_EXPLICITGEN |
raise(SIGSEGV) が実行された |
次の SIGILL 型のシグナルが発生する可能性があります。
ILL_EXECUTION |
不正な操作の試行 |
ILL_EXPLICITGEN |
raise(SIGILL) が実行された |
シグナルの型が SIGFPE,SIGSEGV,または SIGILL であり,浮動小数点プロセッサの状態の破損,整数除算の結果の誤り,オーバーフローしてはならない操作のオーバーフロー,範囲指令の失敗,または不正な操作の試行があった場合,シグナルハンドラからのリターンは一般に推奨できません。リターンが妥当になるのは,ハンドラがレジスタを変更して,妥当な戻りコンテキストが存在する場合,またはシグナルの型が,シグナルが明示的に生成されたことを示している場合(たとえば,FPE_EXPLICITGEN,SEGV_EXPLICITGEN,または ILL_EXPLICITGEN)だけです。一般に,この場合はエラーメッセージを出力し,_exit,exit,または abort を使ってプログラムを終了します。ほかの条件下でリターンを実行した場合,通常,プログラムのアクションは予想できません。
メモ: マルチスレッドプログラムで signal 関数を使用する場合は,特に注意が必要です。SIGINT,SIGTERM,および SIGBREAK シグナルは,Win32 以外のアプリケーションのメインスレッド(スレッド 1)でのみ使用できます。このシグナルの 1 つが発生すると,そのとき実行されているスレッドが中止され,スレッド 1 によって設定されたシグナルハンドラ(ある場合)に制御が移されます。その他のシグナルは任意のスレッドで処理できます。
メモ: セマフォデッドロックが発生する可能性があるため,シグナルハンドラで C++ ランタイムライブラリ関数を使用してはなりません。かわりに,ハンドラは単純にフラグを設定するか,セマフォを送信し,即座に戻る必要があります。
戻り値
成功した場合,signal は,指定されたシグナル型に対する,前のハンドラルーチンへのポインタを返します。
エラーが発生した場合は SIG_ERR を返し,外部変数 errno は EINVAL に設定されます。
例
/* シグナルの例 */
/*
この例では,SIGFPE のシグナルハンドラルーチンをインストールし,
整数オーバーフロー条件を捕捉し,AX レジスタの調整を行い,
戻ります。このプログラムを実行すると,コンピュータが
クラッシュする可能性があります。また,使用しているメモリモデルによっては
実行時エラーが発生します
*/
#pragma inline
#include <stdio.h>
#include <signal.h>
#ifdef __cplusplus
typedef void (*fptr)(int);
#else
typedef void (*fptr)();
#endif
void Catcher(int *reglist)
{
signal(SIGFPE, (fptr)Catcher); // ******シグナルハンドラを再インストールします
printf("Caught it!\n"); *(reglist + 8) = 3; /* AX = 3 を返します */
}
int main(void)
{
signal(SIGFPE, (fptr)Catcher); /* Catcher を適切な型にキャストします */
asm mov ax,07FFFH /* AX = 32767 */
asm inc ax /* オーバーフローになります */
asm into /* ハンドラをアクティブにします */
/* リターン時にハンドラは AX を 3 に設定します。これを行わないと,
「dec」指令の後で次の「into」を実行したときに,別の例外が
発生する可能性があります */
asm dec ax /* オーバーフローになりません */
asm into /* アクティブにしません */
return 0;
}
移植性
POSIX | Win32 | ANSI C | ANSI C++ |
---|---|---|---|
+ |
+ |
+ |
+ |