引进 - 漫长而枯燥的部分
(现在的问题是在结束)第三方代码被修改FPU控制字
我越来越严重的头痛过,保持第三方COM组件改变FPU控制字。
我的开发环境是Windows和Visual C++ 2008.正常的FPU控制字指定在各种情况下不应抛出异常。我已经通过查看在float.h
中找到的_CW_DEFAULT
宏以及在启动时查看调试器中的控制字来验证了这一点。
每次我调用COM对象时,控制字都会在返回时被修改。这很容易防范。我只是重置控制字,一切都很好。问题是当COM组件开始调用我的事件接收器时。只要我收到事件呼叫,我就可以通过重新设置控制字来保护我的代码,但只要我从事件呼叫返回,我就无法做任何事情。
我没有这个COM组件的来源,但我正在与作者联系。我从他那里得到的答复是“呃?”。我不认为他有丝毫的线索我在说什么,所以我担心我必须自己做一些事情。我相信他的运行时(我认为它是Delphi或Borland C++,因为DLL中充满了符号名称,全部以大写字母T开头),或者他正在使用的其他第三方代码,这就是问题所在。我不认为他的代码明确地修改了FPU控制字。
那么,我该怎么办?从业务角度来看,使用这个第三方组件势在必行。从技术角度来看,我可以抛弃它,并自己实施通信协议。但是,这将非常昂贵,因为此协议涉及处理信用卡交易。我们不想承担责任。
我非常需要一个关于Borland产品中的FPU设置的入门知识或一些有用的信息,我可以将这些信息传递给组件的作者。
的问题
有什么我可以做什么?我不认为组件作者有什么需要解决它(通过从他相当无知的反应来判断)。
我一直在玩弄安装我自己的异常处理程序的想法,其中我只是重置处理程序中的控制字,并告诉Windows继续执行。我尝试安装SetUnhandledExceptionFilter()
的处理程序,但由于某些原因,异常未被捕获。
- 为什么我不能捕捉到例外?
- 如果我成功捕捉FPU异常,重置FPU控制字,并让执行继续,因为什么也没有发生 - 都是下注吗?
更新
我要感谢大家对他们的建议。我已经发送了作者的指示,说明他可以做些什么来让生活更加轻松,不仅仅是我,还有许多其他代码的客户。我向他建议,他应该在DllMain(DLL_PROCESS_ATTACH)
处采样FPU控制字,并在稍后保存控制字,以便在调用我的事件处理程序之前重置FPU CW,并从我的调用中返回。
现在,如果有人感兴趣,我有一个黑客入侵。破解可能是一个糟糕的问题,因为我不知道它会如何处理他的代码。我之前已经收到确认,他没有在他的代码中使用任何浮点数,所以这应该是安全的,除非使用某些依赖于FPU异常的第三方代码。
我对我的应用程序所做的两处修改:
- 缠上了我的消息泵
- 安装窗钩(
WH_CALLWNDPROC
)赶角落情况下,消息泵被旁路
在这两种情况下,我检查FPU CW是否已更改。如果有,我将它重置为_CW_DEFAULT
。
http://www.virtualdub.org/blog/pivot/entry.php?id=53;长话短说,他们也在任何“危险的”代码路径之后添加了代码来恢复FPU控制世界,但帖子提到“可以禁用Borland运行时库的这种行为并避免此问题” –
@matteo , 谢谢你的链接。一个有趣的阅读!我会将其转发给作者。 –
顺便说一下,我认为禁用该帖子中提到的行为的方法实际上是使用Set8087CW函数,正如@David在他的回答中所解释的。 –