25 gfortran で浮動小数点演算シグナルを発生させる

(正確に知っていない用語なので、色々と間違えているかもしれないが…)


IEEE754-2008 浮動小数点演算の際には、 Invalid Operation (無効な演算), Division by Zero (0による割り算以外に、 $ \log (0)$ なども含められるようになった), Overflow, Underflow, Inexact という5つの例外 (exception) が定義されている。

これらの例外が発生したとき、(CPUにある)フラグをセットするか (演算の結果も NaN, $ \infty$, $ -\infty$, 0 などにする)、 またはトラップ(trap, 内部割り込みのこと?)を行ってシグナル (SIGFPE, “signal”+”floating-point exception” かな?) を発生するか、 選択できる (Inexact だけはフラグはないと理解している)。

C や Fotran のプログラムを普通にコンパイルした時のデフォールトの処理は、 フラグをセットするようになっているが、シグナルを発生するようにも指定できる。


某 Fortran プログラムをデバッグしていて、 NaN が出力された。それは Invalid operation が発生したということだが、 どこで発生したかは、すぐには分からない。

ソース・プログラムが短ければ、 print *, を撒いて調べることも出来るけれど、 シグナルを発生させて、それをデバッガーで捕まえれば、 楽を出来る(サボれる)と考えた。

gfortran の場合は、コンパイラーに -ffpe-trap=invalid,zero,overflow のようなオプションを渡せば良い。

man gfortran-mp-6 曰く
       -ffpe-trap=list
           Specify a list of floating point exception traps to enable.  On
           most systems, if a floating point exception occurs and the trap for
           that exception is enabled, a SIGFPE signal will be sent and the
           program being aborted, producing a core file useful for debugging.
           list is a (possibly empty) comma-separated list of the following
           exceptions: invalid (invalid floating point operation, such as
           "SQRT(-1.0)"), zero (division by zero), overflow (overflow in a
           floating point operation), underflow (underflow in a floating point
           operation), inexact (loss of precision during operation), and
           denormal (operation performed on a denormal value).  The first five
           exceptions correspond to the five IEEE 754 exceptions, whereas the
           last one (denormal) is not part of the IEEE 754 standard but is
           available on some common architectures such as x86.

           The first three exceptions (invalid, zero, and overflow) often
           indicate serious errors, and unless the program has provisions for
           dealing with these exceptions, enabling traps for these three
           exceptions is probably a good idea.

           Many, if not most, floating point operations incur loss of
           precision due to rounding, and hence the "ffpe-trap=inexact" is
           likely to be uninteresting in practice.

           By default no exception traps are enabled.

ネットを見ていて、gfortran では、 このオプションが悪さをすると書いている人がいたけれど、 どうも何か勘違いしているようだった (最後から2つ目の段落に書いてある -ffpe-trap=inexact に近いことをしていて、変だ変だ言っているとか)。

無事 gdb で例外の発生箇所を特定出来た。

桂田 祐史
2020-04-05