Delphi5中的浮点除零异常

Delphi5中的浮点除零异常,delphi,floating-point,division,delphi-5,divide-by-zero,Delphi,Floating Point,Division,Delphi 5,Divide By Zero,我的应用程序是用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 Pow

我的应用程序是用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分区不同(返回楠或+/-INF而不是引发异常)。


感谢您的指点。

无论如何,这不是一个明确的答案,但

不应该存在的Fpu相关异常可能与未正确清除Fpu堆栈有关。我们在某个阶段遇到了类似的问题,尽管我们遇到了无效的浮点操作异常


本文:有人找到了由
S:=S+'*'引发的无效浮点操作异常的原因,帮助我们解决了问题。

我刚刚尝试了以下代码:

procedure TTTest.FormCreate(Sender: TObject);
var v: extended;
    one: extended;
begin
  one := 1.0;
  v := 100*Power(1.25,one);
end;
它只是按照Delphi5中的预期编译和运行

我猜想,每一个零标记可以设置在代码之外(即使你不链接到C++代码,调用直接X,或者可能会有同样的效果),但是后来在p> 在

Power()
的标准实现中,对
Frac
的唯一调用是测试
Frac(index)=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;
从上面的代码中,您将发现以下命令导致在Delphi6发布之前引发延迟异常:Trunc、Frac、Ceil

所以我猜您在Delphi5中遇到了一个问题,Delphi6已经解决了这个问题。您可能需要使用自己版本的电源,例如:

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;

您是否使用TWebBrowser或任何IE webbrowser组件,如EmbeddedWB

如果是这样,这或许可以解释:


它还包含一些可能解决问题的内容,即使您没有使用上面Jeroen提供的链接所描述的webbrowser(Set8087CW)。

听起来不太可信。我认为您的调试工具没有将您指向正确的位置,或者可能变量没有包含您所认为的内容。不记得D5是否已经拥有它,但您是否尝试过在执行代码时检查CPU/FPU视图中发生了什么?@ldsandon当然D5已经允许使用Alt-F2并进入CPU/FPU视图。好主意。但我猜未处理的FPU异常将在
系统中中断。\u Frac
code。您是否使用任何外部DLL?如果是这样,他们可能已经更改了FPU控制字。在更多信息上看到这篇帖子:很好的答案,为我指出了问题所在。虽然有点吹毛求疵,但答案可以通过解释每一条装配线在做什么来改进——至少对于关键的装配线是这样。或者,总结每个压裂程序的作用(将旧CW推到堆栈上,设置新CW,执行操作,从堆栈中弹出旧CW,诸如此类)。对我们这些不精通x86汇编的人会有所帮助。:)