2017-10-10 99 views
5

Używam programu Fortran 77 napisanego przez kogoś innego. Używam kompilatora gfortran (v5.4.0) w systemie Linux (Ubuntu v.16.04). Nie jestem doświadczonym użytkownikiem skryptów Fortran, gcc lub bash, więc walczę tutaj.Interpretowanie usterek błędu gfortran

Kiedy mój program zakończy działa, pojawia się następujący komunikat:

Note: The following floating-point exceptions are signalling: IEEE_DENORMAL

Musiałem wyglądać ten up - Rozumiem, że niektórzy z moich liczb zmiennoprzecinkowych muszą być przechowywane „Brak reprezentacji” mało precyzyjna forma dla bardzo małych liczb (zamiast spłukiwania ich do zera). Pochodzą one z niestabilnych obliczeń aerodynamicznych w programie - widziałem to podczas wykonywania obliczeń długo. Jest mało prawdopodobne, że te Brak reprezentacji ilości są znacznie wpływając na moje wyniki, ale aby spróbować dowiedzieć się, gdzie/dlaczego tak się dzieje, próbowałem kompilacji z następującymi opcjami błędach:

gfortran –g –fbacktrace –ffpe-trap=invalid,zero,overflow,underflow,denormal –O3 –mcmodel=medium –o ../program.exe

Program skompilowany, ale przy starcie rozbił się i wrócił:

Program received signal SIGFPE: Floating-point exception - erroneous arithmetic operation. 

Backtrace for this error: 
#0 0x7F442F143E08 
#1 0x7F442F142F90 
#2 0x7F442EA8A4AF 
#3 0x4428CF in subroutine2_ at code.f:3601 (discriminator 3) 
#4 0x442C3F in subroutine1_ at code.f:3569 
#5 0x4489DA in code_ at code.f:428 
#6 0x42BdD1 in MAIN__ at main.f:235 
Floating point exception (core dumped) 

mogę zinterpretować je jako hierarchii połączeń, działa wstecz od 6 do 3:

* 6. W linii 235 pliku "main.f" wystąpił problem. [To jest połączenie z "code.f"]

* 5. W linii 428 pliku "code.f" wystąpił problem. [jest to połączenie z "podprogramem1" w "code.f"]

* 4. W linii 3569 "code.f", w "podprocedurze1" wystąpił problem. [jest to połączenie z "podprogramem 2" w "code.f"]

* 3. W linii 3601 "code.f", w "podprocedurze 2" wystąpił problem. [Jest to warunkowe oświadczenie]

if (windspd_2m.ge.5.0) then...

Więc Brak reprezentacji musi być błąd występujący w „następnie” operacji (nie obejmowały tego kodu, ponieważ (a) wiąże się z długą, skomplikowaną serię zależnościami i (b) Mogę rozwiązać błędy matematyczne, to błędy debugowania, z którymi walczę).

Ale dla powyższych błędów 2,1,0 ... Nie wiem, jak interpretować te ciągi liczb/liter. Nie wiem także, co oznacza "dyskryminator 3". Przeszukałem je, ale tylko te zasoby, które znalazłem, wyjaśniają, że przyjmują wyższy poziom wiedzy niż ja. Czy ktoś może mi pomóc zinterpretować te kody błędów, zakładając bardzo małą wcześniejszą znajomość skryptów Fortran, gcc lub bash?

+0

Jesteś na dobrej drodze. Twój program się zawiesza, ponieważ powiedziałeś mu, żeby zawiesił się na wyjątkach zmiennoprzecinkowych za pomocą '-ffpe-trap = ...". Trzy najpopularniejsze ramki stosu to najprawdopodobniej wywołania bibliotek lub funkcji wewnętrznych, które zajmują się faktyczną obsługą błędów. Nie przejmowałbym się tym zbytnio. – chw21

+0

OK, dzięki @ chw21!Brzmi to jak wejście do kodu źródłowego, a znalezienie źródła denoma jest najlepszym sposobem radzenia sobie z tym. Jest szansa, że ​​uzasadnione jest pozostawienie liczb denom w obliczeniach, w zależności od tego, gdzie się znajdują. Przyjrzę się bardziej kontroli nad '-ffpe-trap' - byłoby lepiej, gdybym mógł wygenerować ostrzeżenie zamiast awaryjnego programu. –

+0

* edit: "denom" powinno być "denormalne" –

Odpowiedz

2

Pierwsze trzy klatki stosu wynikają z implementacji śledzenia wstecznego w bibliotece wykonawczej GFortran (libgfortran). Backtrace nie może symbolicznie rozpatrywać adresów w bibliotekach dynamicznych, dlatego otrzymujesz tylko adresy. Jeśli chcesz zobaczyć wyjście symboliczne, możesz dodać "-static" do opcji kompilacji.

Tak więc moim pierwszym przypuszczeniem byłoby, że błąd jest pod kodem.f: 3601, a ponieważ 5.0 jest stałą, to windspd_2m powinien być odormalny.

+0

Witam @janneb, dzięki! Nie wiem, co to jest biblioteka dynamiczna, więc się dowiem. I spróbuję teraz opcji -statycznej. Dla błędu w code.f: 3601, twój wniosek ma sens, ale windpsd_2m jest czerpany bezpośrednio z szeregu czasowego pogody, który nie zawiera żadnych wartości normalnych. Ponieważ jest to warunek, uważam, że błąd występuje w "wtedy" stwierdzeniach, które streściłem w moim poście jako "...", ponieważ ten blok jest dość duży. Zastanawiałem się, czy to właśnie oznaczał ślad zwrotny "dyskryminatora 3" ... w jakiś sposób wskazując, która część "tego" bloku sygnalizowała ... czy to ma sens? –

+0

OK, zrobiłem moją pracę domową na łączu statycznym vs dynamicznym - wydaje się ważne, cieszę się, że dodaję to do mojej bazy wiedzy. Włączenie "-static" przy kompilacji zwraca symboliczne dane wyjściowe dla tych 3 ramek. Jednak dane wyjściowe nie dają nowych informacji, ponieważ te ramki są wywołaniami do gsignal, handlerów ścieżki gfortran i sam ślad śledzenia gfortran. Błąd musi znajdować się gdzieś w instrukcji warunkowej zaczynającej się od code.f: 3601. Czas sprawdzić moją matematykę! –