浮動小数点モデル/エラーの問題は非常に紛らわしいと思います。これは私がよく知らない分野であり、低レベルの C/asm プログラマーではないので、アドバイスをいただければ幸いです。
VS2012 (VC11) で構築された大規模な C++ アプリケーションがあり、浮動小数点例外をスローするように構成しました (より正確には、C++ ランタイムやハードウェアが fp 例外をスローできるようにするため)。それらのリリース (最適化) ビルドでは、デバッグ ビルドではありません。これは、最適化とおそらく浮動小数点モデルによるものだと思います (ただし、コンパイラの /fp:precise スイッチはリリース ビルドとデバッグ ビルドの両方に設定されています)。
最初の質問は、アプリのデバッグの管理に関するものです。fp-exceptions がどこでスローされ、どこで「マスク」されるかを制御したいと考えています。これが必要なのは、(最適化された) リリース ビルド (fp 例外が発生する場所) をデバッグしているためです。また、問題を検出した特定の関数で fp 例外を無効にして、新しい FP の問題を特定できるようにする必要があります。しかし、_controlfp_s を使用してこれを行う (正常に動作する) ことと、コンパイラ (および #pragma float_control) スイッチ "/fp:except" (効果がないように見える) の違いに混乱しています。これら2つのメカニズムの違いは何ですか? それらは fp 例外に対して同じ効果を持つはずですか?
次に、GDI+ dll の呼び出しでスローされたように見える例外を含め、多数の「浮動小数点スタック チェック」例外が発生しています。Web を検索すると、この例外についてのいくつかの言及は、コンパイラのバグが原因であることを示しているようです。これは一般的に当てはまりますか?もしそうなら、どうすればこれを回避できますか? 問題のある関数のコンパイラの最適化を無効にするか、問題のあるコードの領域に対してのみ fp-exceptions を無効にするのが最善ですか? たとえば、この例外をスローする GDI+ 呼び出し (GraphicsPath::GetPointCount への) では、実際に返される整数値は正しいようです。現在、_controlfp_s を使用して、GDI+ 呼び出しの直前に fp 例外を無効にしてから、呼び出しの直後に例外を再度有効にするために再度使用しています。
最後に、私のアプリケーションは多くの浮動小数点計算を行い、堅牢で信頼できる必要がありますが、必ずしも非常に正確である必要はありません。アプリケーションの性質上、浮動小数点値は一般に確率を示すため、本質的に多少不正確です。ただし、ゼロ除算などの純粋な論理エラーをトラップしたいと考えています。これに最適な fp モデルは何ですか? 現在、私は:
- _controlfp_s と SIGFPE シグナル ハンドラを使用して、すべての fp 例外 (つまり、EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE | EM_DENORMAL | EM_INVALID) をトラップします。
- denormals-are-zero (DAZ) と flush-to-zero (FTZ) を有効にしている (つまり、_MM_SET_FLUSH_ZERO_MODE(_MM_DENORMALS_ZERO_ON))、および
- デフォルトの VC11 コンパイラ設定 /fp:precise と /fp:except を使用しています。
これは最高のモデルですか?
よろしくお願いします!