windows - 第三方代码正在修改 FPU 控制字

标签 windows delphi com components fpu

介绍——又长又无聊的部分

(问题在最后)

我对不断更改 FPU 控制字的第三方 COM 组件感到非常头疼。

我的开发环境是Windows和Visual C++ 2008。正常的FPU控制字指定在各种情况下不应该抛出异常。我通过查看 float.h 中的 _CW_DEFAULT 宏以及在启动时查看调试器中的控制字来验证这一点。

每次我调用 COM 对象时,控制字都会在返回时被修改。这很容易防御。我简单地重置了控制字,一切都很好。问题是当 COM 组件开始调用我的事件接收器时。我可以在收到事件调用后立即通过重置控制字来保护我的代码,但是一旦我从事件调用返回,我就无法做任何事情。

我没有这个 COM 组件的源代码,但我正在与作者联系。我从他那里得到的回应是“嗯?”。我不认为他有丝毫线索我在说什么,所以我担心我必须自己做点什么。我相信他的运行时(我认为它是 Delphi 或 Borland C++,因为 DLL 充满了符号名称,全部以大写 T 开头),或者他正在使用的一些其他第三方代码,这导致了问题。我不认为他的代码明确修改了 FPU 控制字。

那么,我能做什么呢?从业务的角度来看,使用这个第三方组件势在必行。从技术角度来看,我可以放弃它,自己实现通信协议(protocol)。然而,这将非常昂贵,因为该协议(protocol)涉及处理信用卡交易。我们不想承担责任。

我迫切需要一个 hack-around,或者一些关于 Borland 产品中 FPU 设置的有用信息,我可以将这些信息传递给组件的作者。

问题

有什么可以做的吗?我不认为组件作者有能力修复它(从他相当无知的回答来看)。

我一直在考虑安装我自己的异常处理程序,我只是重置了处理程序中的控制字,并告诉 Windows 继续执行。我尝试使用 SetUnhandledExceptionFilter() 安装处理程序,但由于某种原因,未捕获异常。

  1. 为什么我没有捕捉到异常?
  2. 如果我成功地捕获了 FPU 异常,重置了 FPU 控制字,然后让执行继续,因为什么也没发生——那么所有的赌注都落空了吗?

更新

感谢大家的建议。我已经向作者发送了说明,说明他可以做些什么来让不仅仅是我,还有他的代码的许多其他客户的生活更轻松。我建议他在 DllMain(DLL_PROCESS_ATTACH) 处采样 FPU 控制字,并保存控制字以备后用,这样他就可以在调用我的事件处理程序之前重置 FPU CW,并从我的事件返回电话。

目前,如果有人感兴趣,我有一个 hack-around。变通可能很糟糕,因为我不知道它会对他的 代码做什么。我早些时候收到确认,他没有在他的代码中使用任何 float ,所以这应该是安全的,除非他使用了一些依赖于 FPU 异常的第三方代码。

我对应用所做的两项修改:

  1. 包装我的消息泵
  2. 安装一个窗口 Hook (WH_CALLWNDPROC) 以捕获绕过消息泵的极端情况

在这两种情况下,我都会检查 FPU CW 是否已更改。如果有,我将其重置为 _CW_DEFAULT

最佳答案

我认为您关于该组件是用 Embarcadero 产品编写的诊断很可能是真的。 Delphi 的运行时库确实启用了浮点异常,C++ Builder 也是如此。

Embarcaderos 工具的一大优点是浮点错误会转换为语言异常,这使得数字编码变得更加容易。这对你没什么安慰!

这整个区域是一个巨大的 PITA。没有关于 FP 控制字的任何规则。这是一场完全免费的比赛。

我不认为捕获未处理的异常不会完成工作,因为 MS C++ 运行时可能已经捕获了这些异常,但我不是该领域的专家,我可能是错的。

我相信您唯一现实的解决方案是在执行到达您的代码时将 FPU 设置为您希望的值,并在执行离开您的代码时恢复它。我对 COM 事件接收器知之甚少,无法理解为什么它们会成为执行此操作的障碍。

我的产品包含一个用 Delphi 实现的 DLL,我遇到了相反的问题。大多数调用的客户端都有一个 FPU 控制字来禁用异常。我们采用的策略是在入口处记住8087CW,在执行代码之前将其设置为标准的Delphi CW,然后在导出处恢复。我们也通过在进行回调之前恢复调用者的 8087CW 来处理回调。这是一个普通的 DLL 而不是 COM 对象,因此它可能更简单一些。

如果您决定尝试让 COM 供应商修改他们的代码,那么他们需要调用 Set8087CW()功能。

但是,由于游戏没有规则,我相信 COM 对象供应商有理由拒绝更改他们的代码并将责任推给您。

如果这不是 100% 的结论性答案,我很抱歉,但我无法将所有这些想法都写进评论中!

关于windows - 第三方代码正在修改 FPU 控制字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6933690/

相关文章:

使用 MSVC 从 Windows Powershell 编译 C 程序

c -/vs.\in CMD 和 C 系统函数中可执行文件的相对路径

delphi - 我如何使用 Delphi 的 PAServer 调试我的 DLL 项目

delphi - 如何获取列出的网页的所有元素Id?

c++ - COM 中的 C++ 函数指针有问题

c# - 如何刷新或刷新 C# Windows 窗体?

node.js - 在 Windows 10 上的 ubuntu 上的 bash 上安装 azure-cli 后无法通过 NodeJs 错误

delphi - 如何使用Delphi检查路径是否指向根文件夹

c++ - 在 SAFEARRAY 上实现 for-each

python - 如何使用python创建com对象