我的应用程序是用Delphi5编写的.我正在使用madExcept来追踪错误.我追踪了一个“浮点dvision by zero”异常,它不应该是.引发它的代码段如下:
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而不是引发异常).
任何指针赞赏.
解决方法
我刚刚尝试了以下代码:
procedure TTTest.FormCreate(Sender: TObject); var v: extended; one: extended; begin one := 1.0; v := 100*Power(1.25,one); end;
它只是在Delphi 5中按预期编译和运行.
我的猜测是,每个零标志的分区可以设置在你的代码之外(即使你没有链接到C代码,调用Direct X等可能会产生相同的效果),但稍后会在_Frac中提出.
在Power()的标准实现中对Frac的唯一调用是测试Frac(指数)= 0.0.
在Delphi 5和Delphi 6之间对Frac的实现进行了修改.
这是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;