2014-12-04 65 views
8

對於我而言,我正在努力拼搏(但徒勞無益)與異常掩碼。德爾福中的掩蔽例外

我開發了一個應用程序,可以對數十萬條記錄進行繁重的浮點計算。顯然,代碼必須能夠處理異常,尤其是那些與浮點計算相關的異常:溢出,ZeroDivide等。

在Windows 7(32位或64位)下,應用程序在許多不同類型的處理器發生錯誤時,條件得到正確處理,引發異常並丟棄記錄。

不幸的是,當我啓動應用程序的目的地運行的時候,問題就開始了:在帶有Intel Xeon E5-2640 v2 CPU和Windows Server 2003 R2的專用服務器上。這裏不會出現異常:帶有錯誤的記錄不會被丟棄,因此結果受到這些機器描述的數值的污染+INF-INF

的問題是,在服務器上的錯誤掩蔽的默認設置是從那些我們在Windows 7中特別找不同,默認情況下調用服務器上的程序GetExceptionMask我發現exZeroDivide如果在Windows調用GetExceptionMask而7這個例外沒有被掩蓋。結果就是我所說的:在服務器上運行應用程序,這些異常不會引發,而是由處理器處理,返回極端值並「污染」數值。

好的,不要驚慌,我說,你只需調用(即在初始化部分)SetExceptionMask,不包括exZeroDivide,但不起作用。或者更好的是,雖然在調用SetExceptionMask之後,異常exZeroDivide不再被屏蔽,當執行帶有浮點計算的代碼時TArithmeticExceptionMask返回的集合GetExceptionMask仍然包含exZeroDivide,所以如果發生錯誤,則不會引發異常。

任何人都可以告訴我什麼是正確的方式叫SetExceptionMask

這就是爲什麼屏蔽默認值可能與計算機和另一臺計算機不同的原因?操作系統或處理器的類型?

謝謝。

+2

這是一個很好的描述,但你可以發佈一些生成異常的示例代碼,以及一個示例來展示你如何處理屏蔽?這將使我們更容易幫助您找到解決方案。 :) – 2014-12-04 01:18:20

+0

我同意,很難說,沒有看到你是如何做到這一點。我建議開始一個全新的測試應用程序,以複製這種行爲,並與我們分享該代碼。 – 2014-12-04 01:24:46

+1

聽起來好像有什麼東西被注入到Server 2003的進程中 - 病毒檢查器,全局鉤子,其他系統監視工具? - 用不正確的值設置FP標誌字。 – 2014-12-04 01:48:16

回答

4

這通常是因爲您正在調用清除掩碼的第三方代碼。它可能是一個你有意使用的圖書館,但更有可能的是你並沒有特別注意調用。一個常見的例子是打印機驅動程序。這些是改變浮點控制標誌的臭名昭着的。

下一步是識別更改控制標誌的那部分代碼。我建議你添加調試跟蹤日誌記錄。打電話給OutputDebugString就足夠了,但是您最好使用更高級的日誌記錄庫。在程序執行時記錄控制標誌的狀態。在找到罪魁禍首之前,您需要幾個週期的添加日誌記錄調用,運行,讀取日誌。一旦找到更改標誌的外部代碼,請確保在外部代碼執行後恢復它們。

這是一個棘手的領域,我害怕。要做對並不容易。外部代碼有時會與控制標誌一起快速鬆動,就好像該代碼是存在的唯一代碼一樣。 Delphi RTL在處理控制標誌方面也不是最好的。例如,Set8087CW不是線程安全的也許不是衆所周知的。

我個人經歷了與我自己的浮點應用程序的鬥爭。但你應該能夠解決這些問題。祝你好運!