第三方代码正在修改FPU控制字 [英] Third party code is modifying the FPU control word

查看:231
本文介绍了第三方代码正在修改FPU控制字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简介 - 长而乏味的部分



(问题在结尾)





我的开发环境是Windows和Visual C ++ 2008.正常的FPU控制字指定了一个第三方COM组件,它不断改变FPU控制字。在各种条件下不应抛出异常。我已经通过查看 _CW_DEFAULT 宏(位于 float.h 中)以及查看控件



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



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



那么,我该怎么办?从商业的角度来看,使用这个第三方组件是非常必要的。从技术的角度来看,我可以放弃它,并且自己实现通信协议。然而,这将是非常昂贵的,因为这个协议涉及处理信用卡交易。我们不想承担责任。



我迫切需要一个黑客,或一些有用的信息,关于FPU设置在Borland产品,我可以传递组件的作者。



问题



有什么做?我不认为组件作者有什么需要修复它(通过判断从他相当无知的响应)。



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


  1. 为什么我不捕获异常?

  2. 如果我成功捕获FPU异常,重置FPU控制字,只让让执行继续,没有发生
  3. b 感谢大家的建议。我已经发送作者指示他可以做什么,使生活更容易不只是我,但许多其他客户的他的代码。我建议他应该在 DllMain(DLL_PROCESS_ATTACH)中采样FPU控制字,并保存控制字以备将来使用,以便在调用我的事件之前复位FPU CW处理程序,并从我的调用返回。



    现在,我有一个黑客如果有人有兴趣。黑客可能是一个坏的,因为我不知道它会对他的代码做什么。我之前已收到确认,他不在他的代码使用任何浮点数,所以这应该是安全的,禁止一些第三方代码,他使用,依赖于FPU异常。



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



    1. 安装窗口钩子( 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() 功能。 p>

    然而,由于游戏中没有规则,我相信COM对象供应商会拒绝改变他们的代码,并把责任推在你身上。 / p>

    对不起,如果这不是100%的结论性答案,但我不能把所有这些想法变成一个评论!


    The introduction - the long and boring part

    (The question is at the end)

    I am getting severe head aches over a third party COM component that keeps changing the FPU control word.

    My development environment is Windows and Visual C++ 2008. The normal FPU control word specifies that no exceptions should be thrown during various conditions. I have verified this with both looking at the _CW_DEFAULT macro found in float.h, as well as looking at the control word in the debugger at startup.

    Everytime I make a call into the COM object, the control word is modified upon return. This is easy to defend against. I simply reset the control word, and all is good. The problem is when the COM component starts calling my event sink. I can protect my code by reseting the control word as soon as I receive the event call, but I can't do anything as soon as I return from the event call.

    I don't have the source for this COM component, but I am in contact with the author. The responses I have had from him has been "Huh?". I don't think he has the slightest clue what I'm talking about, so I fear I have to do something about this myself. I believe that his runtime (I think it's either Delphi or Borland C++, because the DLL is full of symbol names, all starting with capital T) , or some other third party code he's using, that's causing the problem. I don't think his code explicitly modifies the FPU control word.

    So, what can I do? From a business point of view, it is imperative to use this third party component. From a technical point of view, I could ditch it, and implement the communication's protocol myself. However, that would be really expensive, as this protocol involves handling credit card transactions. We don't want to take on the liability.

    I desperately need a hack-around, or some useful information about FPU settings in Borland products that I can pass along to the author of the component.

    The questions

    Is there anything I can do? I don't think the component author has what it takes to fix it (by judging from his rather clueless responses).

    I have been toying with the idea of installing my own exception handler, in which I just reset the control word in the handler, and tell Windows to continue executing. I tried installing the handler with SetUnhandledExceptionFilter(), but for some reason, the exceptions are not caught.

    1. Why aren't I catching the exceptions?
    2. If I succeed with catching FPU exceptions, resetting the FPU control word, and just let the execution continue as nothing has happened - are all bets off then?

    Update

    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:

    1. Wrap my message pump
    2. Install a window hook (WH_CALLWNDPROC) to catch the corner cases where the message pump is bypassed

    In both instances, I check if the FPU CW has changed. If it has, I reset it to _CW_DEFAULT.

    解决方案

    I think your diagnosis that the component is written in an Embarcadero product is very likely to be true. Delphi's runtime library does indeed enable floating point exceptions, same for C++ Builder.

    One of the nice things about Embarcaderos tools is that floating point errors get converted into language exceptions which makes numerical coding a lot easier. That is going to be of little consolation to you!

    This entire area is a colossal PITA. There are no rules whatsoever regarding the FP controls word. It's a total free-for-all.

    I don't believe that catching unhandled exceptions isn't going to get the job done because the MS C++ runtime will presumably already be catching these exceptions, but I'm no expert in that area and I may be wrong.

    I believe that your only realistic solution is to set the FPU to what you want it to be whenever execution arrives in your code, and restore it when execution leaves your code. I don't know enough about COM event sinks to understand why they present an obstacle to doing this.

    My product includes a DLL implemented in Delphi and I suffer from the reverse problem. Mostly the clients that call in have an FPU control word that disables exceptions. The strategy we adopt is to remember the 8087CW on entry, set it to the standard Delphi CW before executing code, and then restore it at the exit point. We take care to deal with callbacks too by restoring the caller's 8087CW before making the callback. This is a plain DLL rather than a COM object so it's probably a bit simpler.

    If you decide to attempt to get the COM supplier to modify their code then they need to call the Set8087CW() function.

    However, since there are no rules to the game, I believe that the COM object vendor would be justified in refusing to change their code and to put the onus back on you.

    Sorry if this is not a 100% conclusive answer, but I couldn't get all these thoughts into a comment!

    这篇关于第三方代码正在修改FPU控制字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆