2012-10-16 189 views
5

學習「try & catch」。下面的代碼有什麼問題? 感謝您的意見。C++異常處理

錯誤執行:

terminate called without an active exception 
Aborted 

代碼:

#include <stdio.h> 
int main() 
{ 
    int a = 3; 

    try 
    { 
    if (a < 5) 
     throw; 
    } 
    catch (...) 
    { 
    printf ("captured\n"); 
    } 

    return 0; 
} 
+0

您的代碼看起來比C C_ish_方式++ _ ish_,只是習慣代碼在C++中,如果你選擇C++爲首選語言,這樣一來你的代碼很容易成爲一種奇怪的混合語言,沒有任何好處,只會讓你的生活變得更加難以學習新東西和有用的東西。的確,C在C++下是沒有問題的,但只是在編碼時嘗試使用更簡單和更線性的方法。 – Ken

回答

4

裏面一個try塊的,你必須指定什麼扔。唯一可以使用throw的地方是在catch塊內,以重新拋出當前異常。如果您自己調用throw而沒有激活當前異常,您將會殺死您的應用,就像您已經發現的那樣。

試試這個:

#include <stdio.h> 

int main() 
{ 
    int a = 3; 

    try 
    { 
    if (a < 5) 
     throw 1; // throws an int 
    } 
    catch (...) 
    { 
    printf ("captured\n"); 
    } 

    return 0; 
} 

您可以throw任何你想要的,只要你扔東西。

+0

說'[你必須在'catch'塊中使用'throw'本身有點含糊,因爲它暗示了一個語法上的限制。事實上,無論什麼時候活動異常,都可以重新進行投票 - 無論範圍如何。 –

+0

@LucDanton:我沒有說你必須自己使用'throw',我說只有你自己可以使用'throw'的地方就在'catch'裏面。如果你不在'catch'裏面,那麼沒有活躍的例外。 –

+0

[一個正確的例子,'throw;'在'catch'塊中沒有語法使用](http://liveworkspace.org/code/85bfc976aec21b24d65293ce9355b7cb)。 –

5

throw;語句試圖重新拋出一個當前異常,但有可能是一個也沒有。你需要像

throw some_exception_object(); 
+2

我推薦'拋出std :: runtime_error(「message」)',但我見過'throw 42'(我相信只能用catch(...)'來捕獲)。 –

+1

@MaxLybbert:可以用catch(int n)來捕獲,但是,拋出非類類型不推薦用於「真實」程序。 – aschepler

+0

謝謝,我剛剛測試過,'catch(int i)'起作用。 –

1

你需要實際拋出一些對象。即使這樣簡單

throw "error"; 

會捕獲你想要的錯誤。

看到它在行動here

4

有四件事情,兩個主要的和兩個小。一兩件事的時間...

1.重新拋出使用W/O激活的異常

一個throw;語句用於重新引發當前捕獲的異常。例如:

try { 
    do_something(); 
} catch (const std::exception &) { 
    throw; // This statement re-throws an exception that was caught in this "catch" block. 
} 

在你的情況,使用的是沒有throw;捕獲任何異常(爲了話 - 它不會出現內部catch塊直接或間接地),從而程序被終止。當需要拋出異常並且不要重新拋出異常時,就像你的情況一樣,你必須指定一個拋出的異常對象。例如:

throw std::runtime_error("Something bad happened"); 

2.包羅萬象的不子句重新拋出捕獲的異常

你包羅萬象的條款(catch (...))是完全合法的C++。但是,它不會重新拋出異常。儘管它是一個合法的C++代碼,但這種用法是一個禁忌。 C和C++運行時通常使用特殊類型的異常來實現某些功能。例如,NPTL正在使用異常來實現線程取消。如果您使用catch (...)捕捉到該異常,則線程將不會被取消,並且您將會遇到不愉快的時間。一般來說,你必須通過類型來捕獲異常。在幾乎所有情況下,例外都是從std::exception繼承,因此您必須編寫catch (const std::exception &)或者,如果您希望獲得確切類型,則可以使用 - catch(const TypeYouExpect &)。但是,如果您必須使用全部捕獲,請記住重新投擲。例如:

try { 
    do_something(); 
} catch (...) { 
    throw; // DO NOT FORGET TO RE-THROW. 
} 

3.標題命名...

您包括C頭,而C++提供了自己的首部標準C的功能。所以,頭:

#include <stdio.h> 

..應該是:

#include <cstdio> 

C++特定的C函數得到特殊待遇。例如,它們在std命名空間中可用。因此,您可以使用std::open()而不是僅使用open()::open()。沒什麼大不了的,但強烈推薦。

4.從主返回。

與C不同,C++的main()函數非常特殊。它允許你不要有return 0;。這是一個默認行爲。所以,除非你真的需要返回一些價值,否則你可以通過不輸入return 0;來節省一些時間。不過請記住,main是唯一類似的功能,除非函數被標記爲void,否則您必須明確地返回其他任何地方。

希望它有幫助。祝你好運!

1

聲明拋出一個例外是:

throw <expression>; 

本聲明:

throw; 

也被稱爲重新throw語句,並使用重新拋出一個現有的異常已抓住。它通常用在catch塊中,例如,查看異常並決定是否可以繼續,重試或中止。如果你決定放棄,你重新拋出異常,以便其他人在調用堆棧下方捕獲並處理這個錯誤。

例如:

// getResult() calls can fail with a deadlock exception 
// This method will retry up to 3 times before failing 
Result getResultWithRetry() 
{ 
    int nbTry = 3; 
    for(;;) { 
     try { 
      return getResult(); 
     } catch (DeadLockException& e) { 
      if (nbTry == 0) { 
       throw; // re-throw the deadlock exception 
      } 
     } 
     --nbTry; 
    } 
} 
+1

提示:由於沒有很好的理由,通過非常量引用捕獲異常是一種不好的做法。除非你真的需要修改這個對象,否則通過不斷的引用來捕獲它。這允許編譯器執行更多優化。 – 2012-10-16 00:31:12