引言——冗长而乏味的部分
(问题在最后)
我对不断更改 FPU 控制字的第三方 COM 组件感到非常头疼。
我的开发环境是Windows和Visual C++ 2008。正常的FPU控制字指定在各种情况下不应该抛出异常。我已经通过查看中_CW_DEFAULT
找到的宏float.h
以及在启动时查看调试器中的控制字来验证这一点。
每次我调用 COM 对象时,控制字都会在返回时被修改。这很容易防御。我只是重置了控制字,一切都很好。问题是当 COM 组件开始调用我的事件接收器时。我可以通过在收到事件调用后立即重置控制字来保护我的代码,但是一旦我从事件调用返回,我就无法做任何事情。
我没有这个COM组件的源代码,但我正在与作者联系。我从他那里得到的回应是“嗯?”。我认为他根本不知道我在说什么,所以我担心我必须自己做点什么。我相信他的运行时(我认为它是 Delphi 或 Borland C++,因为 DLL 充满了符号名称,都以大写 T 开头),或者他正在使用的其他第三方代码,这导致了问题。我不认为他的代码明确修改了 FPU 控制字。
那么,我能做些什么呢?从业务的角度来看,必须使用这个第三方组件。从技术角度来看,我可以放弃它,自己实现通信协议。但是,这将非常昂贵,因为该协议涉及处理信用卡交易。我们不想承担责任。
我迫切需要一个 hack-around,或者一些关于 Borland 产品中 FPU 设置的有用信息,我可以将它们传递给组件的作者。
问题
有什么我可以做的吗?我不认为组件作者有能力修复它(从他相当无能的回答来看)。
我一直在玩弄安装我自己的异常处理程序的想法,我只是在处理程序中重置控制字,并告诉 Windows 继续执行。我尝试使用 安装处理程序SetUnhandledExceptionFilter()
,但由于某种原因,没有捕获到异常。
- 为什么我没有捕捉到异常?
- 如果我成功捕获 FPU 异常,重置 FPU 控制字,然后让执行继续,因为什么都没发生——那么所有的赌注都没有了吗?
更新
I would like to thank everyone for their suggestions. I have sent the author instructions on what he can do to make life easier for not just me, but many other clients of his code. I suggested to him that he should sample the FPU control word at DllMain(DLL_PROCESS_ATTACH)
, and save the control word for later, so that he can reset FPU CW before calling my event handlers, and returning from my calls.
For now, I have a hack-around if anyone is interested. The hack-around is potentially a bad one, because I don't know what it'll do to his code. I have received confirmation earlier that he does not use any floating point numbers in his code, so this should be safe, barring some third party code he uses, that relies on FPU exceptions.
The two modifications I have made to my app:
- Wrap my message pump
- 安装窗口挂钩 (
WH_CALLWNDPROC
) 以捕获绕过消息泵的角落案例
在这两种情况下,我都会检查 FPU CW 是否发生了变化。如果有,我将其重置为_CW_DEFAULT
.