强制gfortran在第一个NaN处停止程序

18

为了调试我的应用程序(Fortran 90),我想把所有的NaN转换成信号NaN。

使用默认设置,我的程序可以正常工作,但输出文件中存在NaN数据。我想要找到生成NaN的位置。如果我能重新编译程序时使用信号NaN,我将在第一个错误浮点操作所在的第一个点收到SIGFPE信号。

1个回答

30

你要寻找的标志是-ffpe-trap = invalid; 我通常添加, zero, overflow以检查相关的浮点异常。

program nantest
    real :: a, b, c

    a = 1.
    b = 2.

    c = a/b
    print *, c,a,b

    a = 0.
    b = 0.

    c = a/b
    print *, c,a,b

    a = 2.
    b = 1.

    c = a/b
    print *,c,a,b
end program nantest

编译并在调试器中运行它会得到:

$ gfortran -o nantest nantest.f90 -ffpe-trap=invalid,zero,overflow -g -static
$ gdb nantest
[...]
(gdb) run
Starting program: /scratch/ljdursi/Testing/fortran/nantest 
  0.50000000       1.0000000       2.0000000    

Program received signal SIGFPE, Arithmetic exception.
0x0000000000400384 in nantest () at nantest.f90:13
13          c = a/b
Current language:  auto; currently fortran

使用英特尔Fortran编译器(ifort),使用选项-fpe0将实现相同的功能。

C / C ++代码有点棘手,我们必须实际插入调用feenableexcept()的代码,该函数启用浮点异常,并在fenv.h中定义;

#include <stdio.h>
#include <fenv.h>

int main(int argc, char **argv) {  
    float a, b, c;
    feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);

    a = 1.;
    b = 2.;

    c = a/b;
    printf("%f %f %f\n", a, b, c);

    a = 0.;
    b = 0.;

    c = a/b;
    printf("%f %f %f\n", a, b, c);

    a = 2.;
    b = 1.;

    c = a/b;
    printf("%f %f %f\n", a, b, c);

    return 0;
}

但作用是相同的:

$ gcc -o nantest nantest.c -lm -g
$ gdb ./nantest
[...]
(gdb) run
Starting program: /scratch/s/scinet/ljdursi/Testing/exception/nantest  
1.000000 2.000000 0.500000

Program received signal SIGFPE, Arithmetic exception.  
0x00000000004005d0 in main (argc=1, argv=0x7fffffffe4b8) at nantest.c:17  
17        c = a/b;  

无论如何,您都可以更好地掌握错误发生的位置。


嗨,是否有可能将相同的选项应用于g++? - osgx
2
使用g++更困难,但可以设置陷阱捕获浮点错误 -- http://trac.hackerwithin.org/wiki/Articles/GccFpe - Jonathan Dursi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接