Подтвердить что ты не робот

Ловушка спокойная NaN

У меня есть приложение, в котором какой-то компонент иногда вставляет qNaN в большой поток данных, что затем делает недействительной всю обработку (БПФ на векторе, содержащем один qNaN, приводит к выходу all-qNaN). Теперь я хотел бы поймать этот компонент в действии и выяснить, почему он это делает.

Для этого мне нужно каким-то образом сделать все сигналы NaN во время отладки. Есть ли способ сделать это, с процессором x64, исполняющим 32-битный код?

4b9b3361

Ответ 1

Если вы хотите, чтобы во время отладки отображались все NaN, переполнения и zerodivides, это возможно.

Для gcc:

#include <fenv.h>

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

Для Visual Studio (не тестируется):

#include <float.h>

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

Ссылки: Microsoft, gcc.


Эти функции позволяют уловить либо NaNs, создаваемые операциями с плавающей запятой (переполнениями, zerodivides, недопустимыми операциями), либо sNaNs, которые используются как входные данные для некоторой операции с плавающей запятой. Они не позволяют поймать qNaN, используемые в качестве входа в операцию с плавающей запятой. Для таких qNaNs единственный способ их найти - проверить каждое значение отдельно (см. Ответ Лучиана Григоре).

Итак, если компонент, который вставляет qNaN, находится в одной и той же программе, вы хотите его поймать или если этот компонент находится в отдельной программе, но у вас есть его исходные коды, просто включите исключения FP с помощью feenableexcept()/_controlfp(). В противном случае проверьте каждое значение во входящем потоке данных с помощью isnan() (С++ 11) или с помощью x != x.

Ответ 2

Я сомневаюсь, что есть способ поместить точку останова данных по всей памяти, чтобы поймать все NaNs.

Я бы поискал код, который вставляет в vector и тестирует для NaN там:

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