ユーザーの例外ハンドラが行う動作はユーザーが自由に設定できます。しかし、ルーチンは、次に示す 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%
|
もちろん、エラーの原因となるソース行を決定するためのより簡単な方法があります。しかし、この例は、例外処理の基本を示すのが目的です。