强制gfortran首先停止编程NaN

问题描述:

要调试我的应用程序(fortran 90),我想将所有NaN都转换为NaN信号。强制gfortran首先停止编程NaN

使用默认设置我的程序没有任何信号,只输出文件中的NaN数据。我想找到生成NaN的点。如果我可以用信号NaN重新编译程序,我会在第一个错误的浮动操作驻留的第一点得到一个SIGFPE信号。

您正在查找的国旗是-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; 

无论哪种方式,您对其中的错误存在的一个更好的处理。

+0

嗨,是否有可能有相同的选项适用于g ++? – osgx 2011-04-24 23:34:58

+2

用g ++很难,但是可以在浮点错误上设置陷阱 - http://trac.hackerwithin.org/wiki/Articles/GccFpe – 2011-04-25 01:40:33