2012-03-08 11 views
13

Mam aplikację, w której jakiś komponent czasami wstawia qNaN do dużego strumienia danych, co z kolei powoduje unieważnienie całego przetwarzania (FFT na wektorze zawierającym pojedynczy qNaN daje wynik na całej qNaN). Teraz chciałbym złapać ten składnik w akcji i dowiedzieć się, dlaczego to robi.Pułapka na pułapkę NaN

W tym celu musiałbym w jakiś sposób sygnalizować wszystkie sygnały NaN podczas debugowania. Czy istnieje sposób, aby to zrobić, z procesorem x64 wykonującym 32-bitowy kod?

+1

Niezupełnie duplikat, ale wiele szczegółów http://stackoverflow.com/questions/570669/checking-if-a-double-or-float-is-nan-in-c – user7116

+0

Kolejne pytanie z dobrymi szczegółami http : //stackoverflow.com/questions/2247447/usefulness-of-signaling-nan – user7116

+0

Powiązane: [Czy mogę uczynić gcc mi powiedzieć, gdy obliczenia wyników NaN lub inf w czasie wykonywania?] (http://stackoverflow.com/questions/2941611/can-i-make-gcc-tell-me-when-a-calculation-results-in-nan-or-inf-at-runtime/20973509) – legends2k

Odpowiedz

20

Jeśli chcesz, aby wszystkie Nans, przelewa i zerodivides sygnalizacji podczas debugowania, jest to możliwe.

Dla gcc:

#include <fenv.h> 

#ifndef NDEBUG 
feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); 
#endif 

Visual Studio (nie sprawdzone)

#include <float.h> 

#ifndef NDEBUG 
_clearfp(); 
_controlfp(_controlfp(0, 0) & ~(_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW), 
      _MCW_EM); 
#endif 

Literatura: Microsoft, gcc.


funkcje te pozwalają, aby złapać albo nieliczby produkowanego przez operacji zmiennoprzecinkowych (przepełnienia, zerodivides, nieprawidłowego działania) lub sNaNs, używane jako dane wejściowe do niektórych operacji zmiennoprzecinkowej. Nie pozwalają one na wychwytywanie qNaNs, używanego jako wejście do operacji zmiennoprzecinkowej. W przypadku takich qNaNs jedynym sposobem na ich znalezienie jest sprawdzenie każdej wartości osobno (patrz odpowiedź Luchiana Grigore'a).

Więc jeśli komponent, który wstawia qNaN jest w tym samym programie, czy chcesz go przechwycić, czy też ten komponent jest w oddzielnym programie, ale masz jego kody źródłowe, po prostu włącz wyjątki FP z feenableexcept()/_controlfp() . W przeciwnym razie sprawdź każdą wartość w przychodzącym strumieniu danych za pomocą isnan() (C++ 11) lub x != x.

+0

Czy umieściłeś to w pliku implementacji? –

+0

@LuchianGrigore, tak, po prostu wywołaj to z main(). –

+0

Hm, nadal nie otrzymałem wyjątku, ale zaakceptowanie go postawiło mnie na właściwej ścieżce z debugowaniem. –

7

Wątpię, że istnieje sposób umieszczenia punktu przerwania danych w całej pamięci, aby złapać wszystkieNaNs.

będę szukać kodu, który wstawia do vector i test NaN tam:

if (x != x) 
    assert(!"NaN detected"); 
+2

Czy istnieje powód, dla którego nie umieściłeś warunku w samym "assert"? –

+0

@LightnessRacesinOrbit Myślałem o tym, ale jest bardziej czytelny dla niewytrenowanego oka w ten sposób. –

+0

Dobrze, skopiuj to. –