インテル® Fortran コンパイラー 19.0 デベロッパー・ガイドおよびリファレンス
SIGNALQQ で確立したハンドラーを使用することにより、簡単な例外処理の要求に対応できる場合があります。このセクションでは、SIGNALQQ を使用した信号処理方法の詳細と Fortran ランタイムルーチン GETEXCEPTIONPTRSQQ の動作内容について説明します。
ここでは、Microsoft* Visual C++* で提供されている C ランタイム・ソース・コードを参照しています。Visual C++* を持っていない場合でも、このセクションを参照することを推奨します。
多くの Fortran アプリケーションは、一般的な例外処理方法として C スタイルの信号処理を使用する UNIX* システムで開発されていました。これらのアプリケーションを Windows* に移植した場合は、C の信号インターフェイスを継続して使用することができます。SIGNALQQ は、純粋な Fortran、または Fortran と C が混在したコードを使用するすべてのアプリケーションの種類で動作します。
SIGNALQQ は、C ランタイム関数 signal() への Fortran ジャケット (言語インターフェイス) ルーチンです。SIGNALQQ を呼び出すと、特定の信号に対して定義した信号ハンドラー (または処理動作) が C ランタイムシステムに登録されます。C ランタイムシステムは、定義したハンドラー (または処理動作) を内部例外処理動作テーブル、または特定の信号をそのハンドラーに関連付けるための変数に保存します。オペレーティング・システムには、この関連付けが通知されません。
Visual C++* があれば、...\MICROSOFT VISUAL STUDIO .NET\VC7\CRT\SRC\WINSIG.C 内の C ランタイム信号ルーチンのコードを参照して、テーブルがどのように管理されているかを調べることができます。テーブル自体は、同じフォルダーにあるソースファイル WINXFLTR.C で定義され、初期化されています。信号が発生すると、C ランタイムシステムはその内部テーブルを検証し、ハンドラーがその信号に対して登録されているかどうかを調べます。ハンドラーが割り当てられていると、定義したルーチンが呼び出されます。
信号が発生したときに定義されているハンドラーを呼び出すのは、C ランタイムシステムであって、オペレーティング・システムではありません。それでは、C ランタイムシステムはどのようにして発行された例外を取得するのでしょうか? 実行ファイルのエントリーポイントは、アプリケーションの種類によって、mainCRTStartup または WinMainCRTStartup のどちらかになります。「アプリケーション (プロジェクト) の種類によるハンドラー」 (または、C ランタイムソース内にあるソースファイル Crt0.c) を参照して、これらのエントリーポイントを確認してください。main() または WinMain() への呼び出しは try-except 構文で囲まれており、その __except 構文に関連付けられているフィルター式が _XcptFilter 関数を呼び出します。_XcptFilter には、例外情報をオペレーティング・システムに提供する 2 つの引数が渡されます。
例外が発生すると、オペレーティング・システムは、例外フィルターの一覧を参照し、EXCEPTION_CONTINUE_SEARCH を返さない例外フィルターを見つけるまで、例外フィルター式を評価します。このとき、オペレーティング・システムは、最も内側に入れ子構造の try-except 構文から評価を開始します。アプリケーションの種類が、Fortran ランタイムシステムからの main と、その main に関連付けられた except 構文を含む場合、Fortran ランタイムフィルターは、C ランタイムフィルターより前に評価されます。Fortran フィルター式は、定義されたハンドラーが SIGNALQQ で確立されているかどうかを調べます。そのようなハンドラーがあると分かった場合、または環境変数 FOR_IGNORE_EXCEPTIONS が設定されている場合、Fortran フィルター式は EXCEPTION_CONTINUE_SEARCH を返し、C ランタイム例外フィルターが例外を処理し、そのハンドラーを取得できるようにします。ハンドラーが確立されていない場合、または環境変数が設定されていない場合は、Fortran ランタイムはデフォルトの例外処理を実行します。
C フィルター関数 _XcptFilter は、オペレーティング・システムからの例外コードと、オペレーティング・システム例外から C 信号コードへのマッピングを比較します。テーブルに一致したものがある場合は、その信号コードに対応するテーブル内の例外処理動作エントリーが使用されます。このテーブルは、特定の信号コードに対する処理動作として SIGNALQQ ハンドラーが記録されるテーブルと同じテーブルです。ハンドラーが確立されると、_XcptFilter から呼び出されます。_XcptFilter は、そのハンドラーを呼び出す前に、例外処理動作テーブル内で、SIG_DFL 信号に対して指定された処理動作をリセットします。例外が発生した場所から処理を続行し、同じ信号が次に発生したらそのハンドラーを呼び出す場合、ハンドラーをその信号の処理動作として再確立するために、SIGNALQQ を再び呼び出さなければなりません。ハンドラールーチンの実行が終了し、_XcptFilter に戻ると、_XcptFilter は、EXCEPTION_CONTINUE_EXECUTION の値をオペレーティング・システムに返します。オペレーティング・システムは、例外の発生した場所から実行を再開します。実行を継続しない場合、ハンドラーはアプリケーションをシャットダウンするための適切な動作を行う必要があります。
すべてのオペレーティング・システムの例外コードが C 信号コードにマップされているわけではありません。ソースファイル WINXFLTR.C でマッピングを参照することができます。以下に WINXFLTR.C 内のマッピングを示します。
オペレーティング・システムの例外コード |
C の信号番号 |
---|---|
STATUS_ACCESS_VIOLATION |
SIGSEGV |
STATUS_ILLEGAL_INSTRUCTION |
SIGILL |
STATUS_PRIVILEGED_INSTRUCTION |
SIGILL |
STATUS_FLOAT_DENORMAL_OPERAND |
SIGFPE |
STATUS_FLOAT_DIVIDE_BY_ZERO |
SIGFPE |
STATUS_FLOAT_INEXACT_RESULT |
SIGFPE |
STATUS_FLOAT_INVALID_OPERATION |
SIGFPE |
STATUS_FLOAT_OVERFLOW |
SIGFPE |
STATUS_FLOAT_STACK_CHECK |
SIGFPE |
STATUS_FLOAT_UNDERFLOW |
SIGFPE |
C ランタイム例外フィルター関数 _XcptFilter が SIGNALQQ で確立したハンドラーを呼び出す際に、ハンドラーに渡される引数は C の信号番号だけです。また、C ランタイムシステムは、オペレーティング・システムが提供する例外情報へのポインターも保存します。このポインターは _pxcptinfoptrs という名前で、Fortran ランタイムルーチンの GETEXCEPTIONPTRSQQ (W*32) を使用して取得できます。_pxcptinfoptrs の定義は、C ヘッダーファイルの signal.h を参照してください。
GETEXCEPTIONPTRSQQ が返す値をハンドラールーチンで使用することで、TRACEBACKQQ を使用してトレースバックを生成することができます。GETEXCEPTIONPTRSQQ は、単に _pxcptinfoptrs を返します。例外情報がプログラムスタック上にあるため、このポインターは、C ランタイムフィルター関数 _XcptFilter の評価が実行されている間だけ有効です。このため、ほかの理由で GETEXCEPTIONPTRSQQ を使用しないでください。
製品のインストール時に作成されるインテル® Fortran のサンプルフォルダーには、GETEXCEPTIONPTRSQQ の使用方法を示す GETEPTRS というサンプルプログラムが含まれています。