Delphi XE2,TWebBrowser,浮点数除以零问题。

5
在 Delphi 2010 和 Delphi 2007 中,我在 WebBrowserBeforeNavigate / WebBrowserDocumentComplete 上使用 Set8087CW 来防止 FPU 错误损坏我的应用程序。但是,在 Delphi XE2 中,至少在 64 位模式下似乎不起作用。当单击链接(任何链接)时,会出现“浮点除以零”的错误。(将网站地址或内容初始加载到 TWebBrowser 中可以正常工作。)调用堆栈显示,这发生在 system32\D3D10Warp.dll 内部(可能由 IE9 使用),响应于 TApplication.ProcessMessage(两者之间有一些 ???)。

1
文档说明(http://docwiki.embarcadero.com/VCL/en/System.Set8087CW):Set8087CW 在64位Windows上:此控制字不控制浮点运算,因为在64位模式下,SSE寄存器用于浮点运算,而不是FPU(浮点运算单元)。但是,在64位模式下仍然存在FPU,因此SGet8087CW设置控制字的值,就像在32位模式下一样。 - teran
1
@teran,是的,但SGet8087CW是什么? - TLama
@TLama,从http://docwiki.embarcadero.com/VCL/en/System.Set8087CW复制的`Set8087CW`中有一个打字错误。 - user743382
2
@Tom 还有SetMXCSR。我的建议是同时使用SetMXCSRSet8087CW。32位和64位的Windows都可以使用FPU和SSE操作,无论Delphi使用什么浮点运算。 - user743382
1
@Tom,抱歉打错了字,我是指FPU(不是FTP)。 - kobik
显示剩余4条评论
1个回答

10

由于64位代码通常使用SSE执行浮点算术,因此您需要在64位上屏蔽SSE异常。

调用 SetMXCSR 来更改SSE单元的控制状态。个人建议遮掩8087异常,因为64位代码完全可以使用8087单元,如果愿意的话。调用Web浏览器代码时要使用的神奇MXCSR值为$1F80,这是MXCSR在Windows中的默认值。

或者,您可以调用SetSSEExceptionMaskSetFPUExceptionMask,将exAllArithmeticExceptions传递给遮盖所有异常。这些便利的方法可以使您的代码更易读。

如果您确信只需要在x86下遮盖8087上的异常,在x64下遮盖SSE上的异常,那么您可以直接调用SetExceptionMask。这将更改x86下的8087控制状态,并更改x64下的SSE控制状态。

如果我必须在设置整个控制状态和使用便利方法之间做出选择,我会设置整个控制状态。这些ActiveX控件是根据您将使用MS工具编写的假设而编写的,并期望特定的FP控制状态。我将为这些控件提供完全符合其预期的控制状态,然后在执行从控件返回时恢复为Delphi控制状态。


谢谢大家的帮助。我接受这个回答作为解决方案,因为它深入地解决了这个问题(我直接使用SetMXCSR进行了测试,似乎也可以工作。我已经更改了我的代码,除了旧代码外还使用了这个方法)。 - Tom
1
+1;谢谢,您介意我在博客中引用您的回答吗? - Jeroen Wiert Pluimers
1
@JeroenWiertPluimers,我当然一点也不介意。请随便。 - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接