ユーザーの例外ハンドラが行う動作はユーザーが自由に設定できます。しかし、ルーチンは、次に示す 3 つの引数を取る、整数型関数でなければいけません。
handler_name( sig, sip, uap )
handler_name は整数関数の名前です。
sig は整数です。
sip は構造体 siginfo を持つレコードです。
uap は使用されません。
例: 例外ハンドラ関数
INTEGER FUNCTION hand( sig, sip, uap ) INTEGER sig, location STRUCTURE /fault/ INTEGER address INTEGER trapno END STRUCTURE STRUCTURE /siginfo/ INTEGER si_signo INTEGER si_code INTEGER si_errno RECORD /fault/ fault END STRUCTURE RECORD /siginfo/ sip location = sip.fault.address ... ユーザーの行う処理 ... END |
64 ビット SPARC アーキテクチャーで実行するには、STRUCTURE 内のすべての INTEGER 宣言を INTEGER*8 で置き換えて、この例を変更する必要があります。
ieee_handler() によって有効にされるハンドラルーチンが例で示すように Fortran で書かれている場合、ハンドラルーチンは 1 番目の引数 (sig) に対しては、一切の参照を行なってはいけません。1 番目の引数は値でルーチンに渡され、loc(sig) としてのみ参照できます。この値はシグナル番号です。この値はシグナル番号です。
次の例では、浮動小数点の例外を検出するためのハンドラルーチンを作成する方法を示します。
SIGFPE は、浮動小数点演算の例外が発生すると必ず生成されます。SIGFPE が検出されると、制御が myhandler 関数に渡され、即座に異常終了します。-g を付けてコンパイルし、dbx を使用すると、例外箇所を突き止めることができます。
例: 例外箇所を突き止め (アドレスを出力して)、異常終了します。
demo% cat LocExcHan.F #include "floatingpoint.h" EXTERNAL Exhandler INTEGER Exhandler, i, ieee_handler REAL:: r = 14.2 , s = 0.0 , t C ゼロ除算の検出 i = ieee_handler( 'set', 'division', Exhandler ) t = r/s END INTEGER FUNCTION Exhandler( sig, sip, uap) INTEGER sig STRUCTURE /fault/ INTEGER address END STRUCTURE STRUCTURE /siginfo/ INTEGER si_signo INTEGER si_code INTEGER si_errno RECORD /fault/ fault END STRUCTURE RECORD /siginfo/ sip WRITE (*,10) sip.si_signo, sip.si_code, sip.fault.address 10 FORMAT(' シグナル ',i4,' コード ',i4,' 16 進アドレス ', Z8 ) Exhandler=1 CALL abort() END demo% f95 -g LocExcHan.F demo% a.out シグナル 8 コード 3 16 進アドレス 11230 異常終了 demo% |
64 ビット SPARC 環境では、各 STRUCTURE 内の INTEGER 宣言を INTEGER*8 で置き換えて、書式中の i4 を i8 で置き換えます。この例では、f95 コンパイラへの拡張により、VAX Fortran の STRUCTURE 文を受け付けられるようにしています。
ほとんどの場合、例外の実際のアドレスを知るということは、dbx だけに意味があります。
demo% dbx a.out (dbx) stopi at 0x11230 ブレークポイントをアドレスに設定する (2) stopi at &MAIN+0x68 (dbx) run プログラムを実行する 実行中: a.out (プロセス id 18803) MAIN で 0x11230 で停止しました MAIN+0x68: fdivs %f3, %f2, %f2 (dbx) where 例外が発生した行番号を表示する =>[1] MAIN()、"LocExcHan.F" の 7 行目 (dbx) list 7 ソースコード行を表示する 7 t = r/s (dbx) cont ブレークポイント後、継続してハンドラルーチンに入る シグナル 8 コード 3 16 進アドレス 11230 異常終了: _kill 0xef6e18a4 でシグナル ABRT (異常終了) が呼び出されました _kill+0x8: bgeu _kill+0x30 現関数: exhandler 24 CALL abort() (dbx) quit demo% |
もちろん、エラーの原因となるソース行を決定するためのより簡単な方法があります。しかし、この例は、例外処理の基本を示すのが目的です。