2011-04-12 46 views
12

要調試我的應用程序(fortran 90),我想將所有NaN都轉換爲NaN信號。強制gfortran首先停止編程NaN

使用默認設置我的程序沒有任何信號,只輸出文件中的NaN數據。我想找到生成NaN的點。如果我可以用信號NaN重新編譯程序,我會在第一個錯誤的浮動操作駐留的第一點得到一個SIGFPE信號。

回答

21

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