gpt4 book ai didi

delphi - 使用 Set8087CW、SetMXCSR 和 TWebBrowser 屏蔽浮点异常

转载 作者:行者123 更新时间:2023-12-03 14:47:35 27 4
gpt4 key购买 nike

由于我在使用 TWebBrowser 和 TEmbeddedWB 时不时收到“浮点除以零”异常,我发现我需要屏蔽除零异常 Set8087CW 或 SetMXCSR。

问题 1:执行此操作的最佳方法是什么:

  1. 在应用程序启动初期屏蔽此类异常,并且不再触及它们(该应用程序是多线程的)?
  2. 使用OnBeforeNavigateOnDocumentComplete屏蔽/取消屏蔽异常的事件? (文档加载后是否有可能出现异常?)

问题 2:仅屏蔽“除以零”而不屏蔽其他内容的最佳“命令”是什么 - 如果应用程序是 32 位,是否还需要屏蔽 64 位异常?

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

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

奇怪的是,微软这么长时间都没有注意到这个问题 - 同样奇怪的是,Embarcardero 也从未注意到它。因为屏蔽浮点异常还可以有效地屏蔽您自己的程序异常以用于该特定目的。

更新

经过一番研究,我的最终解决方案是:

SetExceptionMask(GetExceptionMask() << exZeroDivide);

GetExceptionMask() 的默认状态返回:TFPUExceptionMask() << exDenormalized << exUnderflow << exPrecision 。显然,一些异常已经被屏蔽了 - 这只是添加了 exZeroDivide屏蔽异常。

因此,每次除以零现在都会产生浮点形式的 +INF,而不是异常。我可以接受这一点 - 对于代码的生产版本,它将被屏蔽以避免错误,而对于调试版本,它将被取消屏蔽以检测浮点除以零。

最佳答案

假设您不需要在应用程序代码中取消屏蔽浮点异常,那么最简单的做法无疑是在初始化代码中的某个时刻屏蔽异常。

最好的方法是这样:

SetExceptionMask(exAllArithmeticExceptions);

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

如果您希望在代码中隐藏浮点异常,那么事情就会变得棘手。一种策略是在专用线程中运行浮点代码,以揭露异常。这当然可以工作,但如果您依赖 RTL 函数 Set8087CWSetMXCSR,则不行。请注意,RTL 中控制 FP 单元的所有内容都通过这些函数进行路由。例如 SetExceptionMask 就是这样。

问题是 Set8087CWSetMXCSR 不是线程安全的。似乎很难相信 Embarcadero 会如此无能,以至于生成在线程上下文上运行的基本例程,但又无法保证线程安全。但这就是他们所做的。

想要消除他们留下的困惑是非常困难的,而且要做到这一点需要大量的代码修补。缺乏线程安全性是由于(错误)使用了全局变量 Default8087CWDefaultMXCSR。如果两个线程同时调用 Set8087CWSetMXCSR,则这些全局变量可能会产生将值从一个线程泄漏到另一个线程的效果。

您可以将 Set8087CWSetMXCSR 替换为不更改全局状态的版本,但遗憾的是事情没有那么简单。全局状态用于其他各个地方。这可能看起来不谦虚,但如果您想了解更多有关此事的信息,请阅读我的这份质量控制报告所附的文档:http://qc.embarcadero.com/wc/qcmain.aspx?d=107411

关于delphi - 使用 Set8087CW、SetMXCSR 和 TWebBrowser 屏蔽浮点异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19187479/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com