8

私のアプリは Delphi5 で書かれています。バグを追跡するために madExcept を使用しています。「ゼロによる浮動小数点除算」例外を追跡しましたが、そうであってはなりません。それが発生するコード セグメントは、次のようになります。

val:=100*Power(1.25,c);

ここで、'c' の実際の値は常に '1' です。

ログのスタック トレース:

main thread ($338f8):
00403504 +010 MyApp.exe   System   1970  +5 @FRAC
00479148 +058 MyApp.exe   Math              Power
007ae8a6 +262 MyApp.exe   MyClass  1962 +36 TMyClass.FormMouseWheel

除算が行われたある時点で別の例外がありましたが、除数は変数であり、例外が発生したときに値も「1」でした。デバッグして再現できたこと。

私の質問:何が欠けていますか?私が認識していない浮動小数点除算に関する誤検知はありますか?

さらに、例外ポイントで C++ DLL を使用していません。これは、FP 除算を異なる方法で処理する傾向があるためです (例外を発生させるのではなく、NaN または +/-INF を返す)。

任意のポインタをいただければ幸いです。

4

3 に答える 3

8

次のコードを試しました:

procedure TTTest.FormCreate(Sender: TObject);
var v: extended;
    one: extended;
begin
  one := 1.0;
  v := 100*Power(1.25,one);
end;

Delphi 5 で期待どおりにコンパイルして実行するだけです。

私の推測では、0 フラグごとの除算はコードの外部で設定される可能性があります (C++ コードにリンクしていない場合でも、Direct X などを呼び出しても同じ効果がある可能性があります) が、後で_Frac.

Fracの標準実装での唯一の呼び出しPower()は、 testFrac(Exponent) = 0.0です。

FracDelphi 5 と Delphi 6の間で の実装に変更がありました。

Delphi 5 バージョンは次のとおりです。

procedure       _FRAC;
asm
    FLD     ST(0)
    SUB     ESP,4
    FSTCW   [ESP]
    FWAIT
    FLDCW   cwChop
    FRNDINT
    FWAIT
    FLDCW   [ESP]
    ADD     ESP,4
    FSUB
end;

Delphi 6 バージョンは次のとおりです。

procedure       _FRAC;
asm
    FLD     ST(0)
    SUB     ESP,4
    FNSTCW  [ESP].Word     // save
    FNSTCW  [ESP+2].Word   // scratch
    FWAIT
    OR      [ESP+2].Word, $0F00  // trunc toward zero, full precision
    FLDCW   [ESP+2].Word
    FRNDINT
    FWAIT
    FLDCW   [ESP].Word
    ADD     ESP,4
    FSUB
end;

上記のコードから、Delphi 6 がリリースされる前に、Trunc、Frac、Ceil というコマンドによって遅延例外が発生したことがわかります。

Delphi 5 で問題に直面したと思いますが、これは Delphi 6 で修正されています。次のような独自のバージョンの Power を使用する必要がある場合があります。

function Power(Base, Exponent: Extended): Extended;
begin
  if Exponent = 0.0 then
    Result := 1.0               { n**0 = 1 }
  else if (Base = 0.0) and (Exponent > 0.0) then
    Result := 0.0               { 0**n = 0, n > 0 }
  else
    Result := Exp(Exponent * Ln(Base))
end;
于 2011-11-08T09:03:38.340 に答える
2

絶対的な答えではありませんが…

あるべきではない Fpu 関連の例外は、FPU スタックが適切にクリアされていないことに関連している可能性があります。無効な浮動小数点演算の例外が発生しましたが、ある段階で同様の問題が発生しました。

この記事: Delphi の今日のバグ: によってスローされた無効な浮動小数点演算例外の理由を誰かが突き止めたFPU スタック リークS := S + '*';は、問題の解決に役立ちました。

于 2011-11-08T08:36:16.187 に答える
0

TWebBrowserまたはEmbeddedWBなどのIEWebブラウザーコンポーネントを使用していますか?

もしそうなら、これはそれを説明するかもしれません: https ://forums.embarcadero.com/thread.jspa?messageID=334125&tstart=0

また、上記のJeroenが提供するリンクで説明されているように、Webブラウザー(Set8087CW)を使用していない場合でも、問題を解決する可能性のあるものが含まれています。

于 2011-11-08T13:24:23.760 に答える