引進 - 漫長而枯燥的部分
(現在的問題是在結束)第三方代碼被修改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在他的回答中所解釋的。 –