delphi – 使用Set8087CW,SetMXCSR和TWebBrowser屏蔽浮点异常

前端之家收集整理的这篇文章主要介绍了delphi – 使用Set8087CW,SetMXCSR和TWebBrowser屏蔽浮点异常前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
由于我不时在使用TWebBrowser和TEmbeddedWB时收到“浮点除零”异常,我发现我需要屏蔽除零除异常Set8087CW或SetMXCSR.

Q1:这样做的最佳方法是什么:

>在应用程序启动的早期屏蔽此类异常,再也不要再触摸它们(应用程序是多线程的)?
>使用OnBeforeNavigate和OnDocumentComplete事件来屏蔽/取消屏蔽异常? (文档加载后是否有可能发生异常?)

Q2:什么是最好的“命令”来掩盖“除以零”而没有别的 – 如果应用程序是32位,是否需要屏蔽64位异常?

我正在使用它的应用程序,它始终有TWebBrowser控件可用于显示电子邮件内容.

此外,如果有人可以澄清 – 这是来自Microsoft的TWebBrowser控件的特定错误还是Delphi / C Builder和Microsoft工具之间的区别?如果我在Visual C应用程序中托管TWebBrowser会出现如果会出现除零错误会发生什么 – 它不会被转换为异常但会发生什么 – Visual C将如何处理“除以零”异常呢?

微软很长一段时间都没有注意到这个问题,这有点奇怪 – 也很奇怪,Embarcardero也没有注意到它.因为有效屏蔽浮点异常也会为此特定目的屏蔽您自己的程序异常.

UPDATE

经过一番检查,我的最终解决方案是

SetExceptionMask(GetExceptionMask() << exZeroDivide);

GetExceptionMask()的默认状态返回:TFPUExceptionMask()<< exDenormalized<< exUnderflow<< exPrecision.显然,一些例外已被屏蔽 - 这只是将exZeroDivide添加屏蔽异常中. 因此,现在每个除零都会导致INF在浮点而不是异常.我可以忍受 – 对于代码的生产版本,它将被屏蔽以避免错误,对于调试版本,它将被解除屏蔽以检测浮点除以零.

解决方法

假设您不需要在应用程序代码中取消屏蔽浮点异常,那么最简单的方法就是在初始化代码中的某些位置屏蔽异常.

最好的方法是:

SetExceptionMask(exAllArithmeticExceptions);

这将在32位目标上设置8087控制字,在64位目标上设置MXCSR.您将在Math单元中找到SetExceptionMask.

如果您希望在代码中取消屏蔽浮点异常,则会变得棘手.一种策略是在专用线程中运行浮点代码,该线程取消屏蔽异常.这当然可以工作,但如果您依赖RTL函数Set8087CW和SetMXCSR则不行.请注意,控制FP单元的RTL中的所有内容都通过这些功能进行路由.例如SetExceptionMask.

问题是Set8087CW和SetMXCSR不是线程安全的.似乎很难相信Embarcadero可能会如此无能为力地生成在线程上下文中运行的基本例程但却无法保证线程安全.但这就是他们所做的.

令人惊讶地难以消除它们留下的混乱,并且这样做涉及相当多的代码修补.缺乏线程安全性取决于(错误)使用全局变量Default8087CW和DefaultMXCSR.如果两个线程同时调用Set8087CW或SetMXCSR,则这些全局变量可能会将值从一个线程泄漏到另一个线程.

您可以将Set8087CW和SetMXCSR替换为不改变全局状态的版本,但遗憾的是并非如此简单.全球状态用于其他各个地方.这可能看起来不合时宜,但如果您想了解更多有关此事的信息,请阅读我在QC报告中附带的文件http://qc.embarcadero.com/wc/qcmain.aspx?d=107411

猜你在找的Delphi相关文章