Я считаю, что проблемы с моделью/ошибкой с плавающей запятой довольно запутанны. Это область, с которой я не знаком, и я не программист с низким уровнем C/asm, поэтому я был бы признателен за немного советов.
У меня есть довольно большое приложение на С++, построенное с помощью VS2012 (VC11), которое я настроил на то, чтобы вызывать исключения с плавающей запятой (точнее, чтобы среда выполнения С++ и/или аппаратное обеспечение выдавали исключение fp) - и это бросание довольно много в выпуске (оптимизированной) сборке, но не в сборке отладки. Я предполагаю, что это связано с оптимизацией и, возможно, с плавающей точкой (хотя компилятор /fp: точный переключатель установлен как для релизов, так и для отладочных сборников).
Мой первый вопрос касается управления отладкой приложения. Я хочу контролировать, где выбрасываются исключения fp и где они "замаскированы". Это необходимо, потому что я отлаживаю (оптимизированную) сборку релиза (где происходят исключения fp) - и я хочу отключить исключения fp в определенных функциях, где я обнаружил проблемы, поэтому я могу найти новые проблемы с FP. Но меня смущает разница между использованием _controlfp_s для этого (что прекрасно работает) и коммутатором компилятора (и #pragma float_control) "/fp: except" (что, кажется, не имеет эффекта). В чем разница между этими двумя механизмами? Предполагают ли они, что они имеют одинаковый эффект на исключениях fp?
Во-вторых, я получаю несколько исключений с проверкой стека с плавающей запятой, в том числе тот, который, похоже, вызывается при вызове GDI + dll. Поиск в Интернете, несколько упоминаний об этом исключении, похоже, указывают на то, что это связано с ошибками компилятора. Это вообще так? Если да, то как мне обойти это? Лучше ли отключать оптимизацию компилятора для проблемных функций или отключать исключения fp только для проблемных областей кода, если не отображаются какие-либо плохие значения с плавающей запятой? Например, в вызове GDI + (в GraphicsPath:: GetPointCount), который генерирует это исключение, фактическое возвращаемое целочисленное значение кажется правильным. В настоящее время я использую _controlfp_s для отключения fp-исключений непосредственно перед вызовом GDI +, а затем снова использовать его для повторного включения исключений непосредственно после вызова.
Наконец, мое приложение действительно делает много вычислений с плавающей запятой и должно быть надежным и надежным, но не обязательно очень точным. Характер приложения заключается в том, что значения с плавающей запятой обычно указывают вероятности, поэтому по своей сути несколько неточны. Тем не менее, я хочу уловить любые чистые логические ошибки, такие как деление на ноль. Какая лучшая модель fp для этого? В настоящее время я:
- захват всех исключений fp (т.е. EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE | EM_DENORMAL | EM_INVALID) с использованием _controlfp_s и обработчика сигналов SIGFPE,
- включили денормалы-ноль (DAZ) и flush-to-zero (FTZ) (т.е. _MM_SET_FLUSH_ZERO_MODE (_MM_DENORMALS_ZERO_ON)) и
- Я использую настройки компилятора VC11 по умолчанию /fp: точный с /fp: кроме не указанных.
Является ли это лучшей моделью?
Спасибо и приветствую!