Fortran/エラーの捕捉

出典: フリー教科書『ウィキブックス(Wikibooks)』
Wikipedia
Wikipedia
ウィキペディアFortranの記事があります。

通常、エラーが発生すると、プログラムは停止し、エラーメッセージが表示されます。ただし、readwrite文の括弧付き制御リストの末尾に、err=labelを追加することで、エラー発生時にジャンプする行を指定できます。

現代のFortran(Fortran 90以降)では、主に次の4つのエラー捕捉領域が導入されています:

  1. ファイル処理とI/O操作のエラー処理
  2. IEEE浮動小数点エラーの検出と報告
  3. 動的割り当て
  4. コマンドライン操作

ファイル処理とI/O操作[編集]

すべての外部ファイル処理文およびI/O操作(openreadwritecloseinquirebackspaceendfileflushrewind、およびwait)は、オプションのiostatおよびiomsg句を受け入れるようになりました。 iostatは、エラーが発生した場合に非ゼロの値を返します。その場合、iomsgに割り当てられた文字変数は簡潔なエラーメッセージを返します。非ゼロの整数とメッセージは、コンパイラに依存しますが、組込みモジュールiso_fortran_envを介して重要な値iostat_endiostat_eorにアクセスできます。エラーが発生し、iostatが非ゼロの場合、実行は停止しません。 ERR句はまだサポートされていますが、使用されるべきではありません。

[編集]

integer :: my_iostat
character (256) :: my_iomsg

open (file='my.dat', unit=10, iostat=my_iostat, iomsg=my_iomsg)
if (my_iostat/=0) then
    write (*,*) 'Open my.dat failed with iostat = ', my_iostat, ' iomsg = '//trim(my_iomsg)
end if

メッセージ文字の必要な長さは、ベンダーおよびエラーに依存します。

IEEE浮動小数点エラーの検出と報告[編集]

これは大きなトピックですが、本質的には、現代のFortranは3つの組込みモジュールIEEE_arithmeticIEEE_exceptions、およびIEEE_featuresへのアクセスを提供します。これらの機能を使用して、ゼロで割るエラーやオーバーフローなどのエラーを検出できますが、その代わりにパフォーマンスが若干低下します。

IEEE_featuresモジュールは、プログラマが必要とする機能へのアクセスを制御し、プログラマが使用ステートメントを配置するスコープユニットでの使用関連付けによって制御されます。

[編集]

subroutine blah
    use, intrinsic :: ieee_features
    
    ! ...
end subroutine blah

Metcalfらによる『Modern Fortran Explained』(OUP)の第11章を参照してください。プログラマが望む場合には、必要な基本的な機能がすべて揃っており、try/catchシステムを構築することができます。

訳註
Fortranでは、組み込みモジュールIEEE_arithmetic、IEEE_exceptions、およびIEEE_featuresを使用して、try-catchの機能を模倣することができます。以下に、簡単な例を示します。
program try_catch_example
    use ieee_arithmetic, only: ieee_is_nan
    implicit none
    
    real :: result
    integer :: status
    
    ! Try
    result = divide(10.0, 0.0, status)
    
    ! Check for error
    if (status /= 0) then
        print *, "Error occurred during division operation."
    else
        print *, "Result of division: ", result
    end if
    
contains
    
    ! Custom division function
    real function divide(dividend, divisor, status)
        real, intent(in) :: dividend, divisor
        integer, intent(out) :: status
        
        if (ieee_is_nan(divisor)) then
            status = 1 ! Indicate divide by zero error
            divide = 0.0 ! Return 0 as result
        else
            status = 0 ! No error
            divide = dividend / divisor
        end if
    end function divide

end program try_catch_example
この例では、ieee_arithmeticモジュールからieee_is_nan関数を使用して、ゼロで割るエラーを捕捉しています。status変数を使用してエラー状態を示し、それに応じて処理を行っています。このように、Fortranでは独自のエラーハンドリング機構を実装することができます。

動的割り当て[編集]

現代のFortranでは、任意の型の配列の実行時の割り当てと解放が可能であり、典型的なエラーは、メモリが不足しているために配列を動的に割り当てようとするか、既に割り当てられていない配列を解放しようとすることです。プログラムの失敗を防ぎ、プログラマが回避策を講じることを許可するために、オプションの句statおよびerrmsgが使用されます。

[編集]

real, allocatable, dimension (:) :: x
integer :: my_stat
character (256) :: my_errmsg

allocate (x(100000000), stat=my_stat, errmsg=my_errmsg)
if (my_stat/=0) then
    write(*,*) 'Failed to allocate x with stat = ', my_stat, ' and errmsg '//trim(my_errmsg)
end if

これらの機能は、等価の共配列機能でも利用できます。

コマンドライン操作[編集]

現代のFortranは、コマンドライン操作の実行に対するエラー検出もサポートしています。

[編集]

integer :: my_cmdstat
character (256) :: my_cmdmsg

call execute_command_line('my.exe', cmdstat=my_cmdstat, cmdmsg=my_cmdmsg )
if (my_cmdstat/=0) stop

この例では、my.exeプログラムのプログラマが、返されるコードと公開されるエラーメッセージを制御します。 ただし、-1および-2は、コンパイラベンダーがサポートされる機能を示すために予約されています。