8

TWebBrowser と TEmbeddedWB を使用しているときに「ゼロによる浮動小数点除算」例外が時々発生するため、ゼロ除算例外 Set8087CW または SetMXCSR をマスクする必要があることを発見しました。

Q1:これを行うための最良のアプローチは何ですか:

  1. アプリケーションの起動の早い段階でそのような例外をマスクし、二度とそれらに触れないようにするには (アプリはマルチスレッドです)?
  2. イベントを使用OnBeforeNavigateしてOnDocumentComplete例外をマスク/マスク解除しますか? (ドキュメントが読み込まれた後に例外が発生する可能性はありますか?)

Q2: 「0 による除算」のみをマスクし、他には何もマスクしない最適な「コマンド」は何でしょうか? アプリケーションが 32 ビットの場合、64 ビットの例外もマスクする必要がありますか?

私が使用しているアプリケーションには、電子メールの内容を表示するためにいつでも利用できる TWebBrowser コントロールがあります。

また、誰かが明確にできる場合、これは Microsoft の TWebBrowser コントロールの特定のバグですか、それとも Delphi/C++ Builder と Microsoft ツールの単なる違いですか? ゼロ除算エラーが発生した場合、Visual C++ アプリケーション内で TWebBrowser をホストするとどうなりますか?例外には変換されませんが、その場合、Visual C++ は「ゼロ除算」例外をどのように処理しますか?

Microsoft がこれほど長い間この問題に気付かなかったのは奇妙なことです。また、Embarcardero もこれに気付かなかったのも奇妙です。浮動小数点例外をマスクすると、その特定の目的のために独自のプログラム例外も効果的にマスクされるためです。

アップデート

いくつかの検討後の私の最終的な解決策は次のとおりです。

SetExceptionMask(GetExceptionMask() << exZeroDivide);

GetExceptionMask()からのデフォルト状態は次を返します: TFPUExceptionMask() << exDenormalized << exUnderflow << exPrecision. したがって、明らかに、一部の例外は既にマスクされています。これはexZeroDivide、マスクされた例外に追加されるだけです。

その結果、すべてのゼロ除算は、例外ではなく浮動小数点の+INFになります。私はそれに耐えることができます-コードの製品バージョンでは、エラーを回避するためにマスクされ、デバッグバージョンでは、ゼロによる浮動小数点除算を検出するためにマスクが解除されます。

4

1 に答える 1

9

アプリケーション コードで浮動小数点例外をマスク解除する必要がないと仮定すると、最も簡単な方法は、初期化コードのある時点で例外をマスクすることです。

これを行う最良の方法は次のとおりです。

SetExceptionMask(exAllArithmeticExceptions);

これにより、32 ビット ターゲットでは 8087 コントロール ワードが設定され、64 ビット ターゲットでは MXCSR が設定されます。SetExceptionMaskユニットで見つかりますMath

コードで浮動小数点例外をマスク解除したい場合は、注意が必要です。1 つの戦略は、例外のマスクを解除する専用スレッドで浮動小数点コードを実行することです。Set8087CWこれは確かに機能しますが、RTL 関数とに依存している場合は機能しませんSetMXCSR。FP ユニットを制御する RTL 内のすべてがこれらの関数を経由することに注意してください。たとえばSetExceptionMaskそうです。

問題は、Set8087CWSetMXCSRがスレッドセーフでないことです。Embarcadero が、スレッド コンテキストで動作する基本的なルーチンを生成するのに無能でありながら、スレッド セーフではない可能性があるとは信じがたいようです。しかし、それは彼らがしたことです。

彼らが残した混乱を元に戻すのは驚くほど難しく、そのためにはかなりの数のコードにパッチを当てる必要があります。スレッド セーフの欠如は、グローバル変数Default8087CWDefaultMXCSR. 2 つのスレッドが同時にSet8087CWorを呼び出した場合、これらのグローバル変数は、一方のスレッドから他方のスレッドに値をリークする効果を持つ可能性があります。SetMXCSR

Set8087CWandをグローバル状態を変更しないバージョンに置き換えることもできますがSetMXCSR、残念ながらそれほど単純ではありません。グローバル状態は、他のさまざまな場所で使用されます。これは慎みのないように思えるかもしれませんが、この件について詳しく知りたい場合は、この QC レポートに添付されている私の文書をお読みください: http://qc.embarcadero.com/wc/qcmain.aspx?d=107411

于 2013-10-04T18:14:44.567 に答える