2014-09-29 137 views
2

簡介: 在Java中,如果你不捕捉異常,你的代碼甚至不進行編譯,並在未處理的異常編譯器崩潰。C++/GCC:如何檢測未處理的異常在編譯時

問: 有沒有辦法告訴GCC是「嚴」與Java在這種情況下,要加一個錯誤,或者至少在未處理的異常警告?

如果不是 - 是否有集成開發環境(對於Unix,請),可以凸顯這種情況下,作爲一個警告?

+4

由於任何函數可以在沒有正式規範的情況下拋出異常,這是不可能的。請記住,「崩潰」(像分段錯誤)不是可以用C++'catch'語句捕獲的異常,它們也可以發生在任何地方。 – 2014-09-29 07:39:24

+0

我同意分段錯誤。我只是想避免拋出和處理異常的突然崩潰。我想知道所有可能引發異常並調用它們的調用 – SomethingSomething 2014-09-29 07:50:03

+1

未處理異常的默認行爲是調用std :: terminate。自定義處理程序可以使用['std :: set_terminate'](http://en.cppreference.com/w/cpp/error/set_terminate)來安裝。它可能無法解決您的緊急問題,但它可以讓您的應用程序最後一次「注視」未知的異常。 – Niall 2014-09-29 07:55:33

回答

0

你可以把一個C的唯一保證++的功能是它永遠不會拋出異常都:

void f() noexcept; 

然而,這在運行時將終止該程序時,會拋出異常。它在編譯時沒有被驗證。

如果你想保證一個錯誤的處理,就可以得到返回了一個成員函數,它接受兩個回調包裝boost::variant<OK, Error>一個類型的值最接近:爲OK情況下的回調,一個用於Error案件。

+0

我想拋出異常並處理它們,因爲它提供了豐富的調試消息,所以'noexcept'不適合我。 {ok,error}結構體是我在'Perl'中常用的一種解決方案,但我認爲在C++中我將能夠有效地使用異常機制..如果我沒有選擇,我可以使用這個解決方案 – SomethingSomething 2014-09-29 07:53:44

2

在C++中是不可能的。異常規範是一個函數聲明但不是它類型的部件的一部分。任何間接調用(通過指針或虛擬調用)都會完全清除有關異常的任何信息。

異常規範在C++ 11贊成noexcept反正棄用,因此,這是不可能的編譯器會不怕麻煩來加強這方面的語言功能。

+0

哪個特徵被描述在C++ 11中? – SomethingSomething 2014-09-29 08:00:42

+2

[異常規範](http://en.cppreference.com/w/cpp/language/except_spec)支持'noexcept',@ user3322273。 – Mat 2014-09-29 08:06:53

0

你可以隨時使用:

int main() 
{ 
    try { 
     ... your usual main ... 
    } 
    catch(...) 
    { 
     std::cerr << "Unhandled exception caught" << std::endl; 
    } 
} 

然而,這是一個相當差的解決方案。

不幸的是,C++的性質使得它很難趕上那裏的東西拋出一個異常的情況,它沒有處理,因爲幾乎一切都已經拋出異常的潛力。我只能想到代碼審查 - 也許代碼分析工具,如圍繞CLANG構建的代碼分析工具將具有這樣做的能力,但它可能不會100%準確。事實上,我甚至不確定Clang Analyzer是否完全理解throw/try/catch,因爲它似乎沒有發現一些相當基本的錯誤http://clang-analyzer.llvm.org/potential_checkers.html(請參閱「例外」標題)。

0

首先,你的關於Java的說法是錯誤的;只有特定的 類型的異常會阻止編譯代碼。而對於 ,大部分情況下,這些類型的例外都與 相對應,它們可以更好地由返回碼處理。例外的是,通常只有 一個合適的解決方案,通過 傳播錯誤了大量的功能時,你不希望有添加 異常規範所有的這些功能。

這真的是爲什麼Java使得它的不同之處:例外 從java.lang.Error派生平時應崩潰 (斷言失敗和類似於C++);並且 從java.lang.RuntimeException派生的例外應該是 C++中的例外。因爲它不是 合理的讓每個函數聲明它可能會拋出 其中之一。

至於其他方面,您希望立即在調用代碼中捕獲 的例外情況,通常最好通過返回碼處理 ,而不是例外; Java在這裏可能會使用異常 ,因爲它沒有輸出參數,這會使得使用 返回代碼更加尷尬。當然,在C++中,你也可以用 靜靜地忽略返回碼,這是一個缺點(但是 歷史原因等)。但真正的問題是合約, 這遠比函數f可能拋出/返回x更復雜; 它更符合「功能f 投擲/返回x, 如果條件c滿足」。而且我知道沒有任何語言有 強制執行的手段。在C++中(對於Java中的檢查異常 ),異常規範更多地沿着 的行「函數f不會拋出任何東西,但x」。其中一般 不是很有用,除非「x」表示全部例外。爲了 編寫真正健壯的代碼,您需要保證永遠不會拋出的幾個函數。有意思的是,你可以用這個 在C++中指定它,包括pre-C++ 11(throw())和 (noexcept);你不能用Java,因爲你不能指定 函數不會拋出java.lang.RuntimeError

(或A java.lang.Error,但是這不是一個問題,因爲如果 你得到其中的一個,你的應用程序反正大清洗。只是 你怎麼有望從 java.lang.VirtualMachineError恢復?當然,你不能 真的希望能夠從段違反 C++或者恢復雖然... java.lang.OutOfMemoryErrorjava.lang.VirtualMachineError派生 。雖然不容易,而不是 總是適用的,我已經寫C++代碼,成功 恢復從std::bad_alloc。)