2011-01-25 72 views
7

是否有跨平臺的方式來處理CPU異常,如分段錯誤或零除?比方說,我需要調用一些潛在的不安全函數(例如來自插件文件),這可能會導致段錯誤,或者其他一些我在執行之前無法測試的問題。我知道,C標準庫具有信號處理功能,但我不知道如何使用它們來處理問題,以避免程序終止(我猜,我不能只是跳到有問題的函數執行之前的位置,還是我可以?)。 在windows下,我可以使用SEH異常處理程序,但是我無法在Linux或任何其他操作系統下執行此操作。如何使用我自己的異常處理程序來處理這些問題,Windows/Linux之間的差異有多大?這甚至可能(通過彙編 - 可以說只是在x86平臺上)?在C++中處理CPU異常

我主要是出於好奇而問,我沒有試圖解決一個存在的問題(但)。 謝謝

+0

這可能是有趣的:http://stackoverflow.com/questions/4747934/c-catch-a-divide-by-zero-error – 2011-01-25 15:24:22

+1

而在一個段錯誤的情況下,你不能做任何事情,我必須承認除數爲零,溢出和下溢的情況總是讓我感到困惑,能夠抓住它們會很好。 – 2011-01-25 16:23:08

回答

5

libsigsegv是一個用於處理分段錯誤和堆棧溢出的跨平臺庫。但是,在絕大多數情況下,當您檢測到分段錯誤時,正確的做法是儘可能快地終止執行,而不是嘗試從中恢復。段錯誤通常指示錯誤或內存損壞,一旦內存損壞,實際上不可能從內存中恢復。

2

問題是,如果插件段故障,你不能保證你的主程序將在什麼狀態了。即使你可以捕獲SIGSEGV(我相信你可以),你也不會有一種很好的方式來恢復你的應用程序。

你需要做的是在fork ed過程中運行插件,這樣如果它崩潰你的主程序也不會被取消。例如,您可以使用管道在進程之間進行通信。

+0

插件的例子只是一個可能使用它的想法。這樣的插件必須按照您的建議或者作爲子流程運行,或者必須遵循一套嚴格的規則,如它可能會或可能不會做的那樣(但是我再次無法執行這個)。但是,如果我只需要讀/寫某些內存,我應該能夠在段錯誤的情況下恢復。 – 2011-01-25 15:36:25

1

不,沒有標準的方法。在C++中,這種「CPU異常」是未定義行爲的表現,即C++標準沒有規定任何有關它們的行爲或任何後來發生的事情。標準C++中不存在「segfault」的概念。取消引用NULL指針可能會引發您的計算機着火,顯然,在這一點上幾乎沒什麼可抓的。

C也沒有解決這個問題:SIGSEGV不是一個標準的C信號;這是一個POSIX擴展。例如,Windows沒有SIGSEGV。

2

這不包括在標準C++中,但常見的桌面操作系統提供了執行此操作的工具。 Windows具有結構化異常處理(SEH),相關編譯器擴展可用,而POSIX提供信號處理。

通常,我會說你不應該捕捉CPU異常 - 它們只發生在你的程序被竊聽的時候,並且在那個時候,是時候展開一個調試器,而不是繼續。

即使在彙編程序中,也不能使用相同的方法。這些設施由操作系統提供 - 當CPU引發異常時,它會去操作系統決定如何處理它,而不是用戶模式。不僅如此,我還會說SEH和信號處理很容易在代碼中使用它們時會有根本不同的方法,所以簡單的#ifdef不會削減它。

setjmplongjmp只能用於由用戶模式代碼引發的「信號」,而不是OS級別。

0

信號處理程序可以修復了程序執行到某個點;在信號(7)手冊頁中記錄了什麼是允許的。

有實現,將

  • 返回從SIGSEGV處理程序錯誤指令(這允許您更改內存映射和返回),並

  • 去指示故障以下對於SIGFPE(因此您的信號處理程序需要查找指令並提供結果)

請注意,最好定義。手冊告訴你不要依賴任何這些。你被警告了。 :)