Заставить gfortran остановить программу сначала NaN

Чтобы отладить мое приложение (fortran 90), я хочу превратить все NaN в сигнальные NaN.

При настройках по умолчанию моя программа работает без каких-либо сигналов и просто выводит данные NaN в файл. Я хочу найти точку, в которой генерируется NaN. Если я могу перекомпилировать программу с сигнализацией NaN, я получу сигнал SIGFPE в первой точке, где находится первая неправильная операция с плавающей запятой.


person osgx    schedule 12.04.2011    source источник


Ответы (1)


Вам нужен флаг -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

С компилятором Intel 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;  

в любом случае, вы гораздо лучше поймете, где возникают ошибки.

person Jonathan Dursi    schedule 12.04.2011
comment
Привет, можно ли применить тот же параметр к g ++? - person osgx; 25.04.2011
comment
С g ++ сложнее, но можно установить ловушки для ошибок с плавающей запятой - trac.hackerwithin. org / wiki / Articles / GccFpe - person Jonathan Dursi; 25.04.2011