2008-11-26 101 views
0

我在C++中使用了標準異常處理方法。這是try {}和catch {}塊。在我的代碼,FUNC1()將拋出一個異常,而FUNC2是這樣的:C++異常處理程序的一個奇怪問題

bool func2() 
{ 
    try{ 
     func1(); 
    } 

    catch(myException& e) 
    { 
     cerr << "error!" << endl; 
     return false; 
    } 
    return true; 
} 

但是當我運行我的代碼,一個奇怪的事情發生了。我從來沒有達到拋出異常的代碼,但我總是在catch塊中到達返回false的行(但是cerr <<的行從未到達)。然後該函數繼續返回true。我不知道原因是什麼。任何人都可以幫我解決這個問題嗎?非常感謝你!

回答

0

在WinDbg(或gdb)中打開您的應用程序,並啓用第一次機會例外(通過sxe eh在WinDbg中)。

7

如果您在編譯器中使用了任何優化標誌(即不是調試模式),則不能相信調試器向您顯示正確的執行線。你做出矛盾的表述 - 「返回false」語句正在執行,但函數返回true。這是我能想到的唯一解釋。

+0

對不起,你能解釋一下嗎?該函數僅在發生異常時才返回false,否則返回true。我不明白爲什麼它每次進入catch block都會返回false。然後它不會真的返回,因爲它將在稍後返回。 – user26404 2008-11-26 03:27:22

+0

當您運行高度優化的代碼時,CPU正在運行的指令可能與源代碼不完全對齊,因此您會在調試器中看到一些無意義的結果。 – 2008-11-26 03:33:00

+0

當我將「return false」語句更改爲assign語句時,沒有錯誤。 catch {}塊返回有什麼問題嗎?在catch塊中返回 – user26404 2008-11-26 05:53:06

-1

使用調試模式,未優化模式。另外,確保你沒有寫信給任何懸掛指針。

0

你怎麼知道它達到了返回錯誤?如果func2沒有執行cerr並返回true,那麼聽起來沒有任何異常被捕獲,並且返回false不被執行。

如果您使用的是調試器,有時會在沒有引發異常時顯示您位於catch塊的右括號中,這可能會引起混淆。

3

正如@Mark Ransom所說,您可能已啓用優化功能。爲了幫助您瞭解什麼是goind上,這是代碼的編譯器可能產生的C++相當於:

bool func2() 
{ 
    bool ret; 

    try{ 
     func1(); 
     ret = true; 
    } 

    catch(myException& e) 
    { 
     cerr << "error!" << endl; 
     ret = false; 
    } 

    return ret; 
} 

但是,當你在上生成的代碼return ret;「線」,有2原始代碼中的行可能實際上位於:return false;return true;。調試器不知道哪一個是正確的,因此它顯示第一個(實際上,它是編譯器生成調試器將使用的表,這使得選擇)。

如果您告訴編譯器生成一個程序集文件並查看它,這將更加明顯。假設這是x86,其中返回值爲%eax,兩個分支將設置%eax爲1或0,然後跳轉或通過公共函數結尾代碼(這是實際從函數返回的位置)。

0

如果你正在擊中返回true語句是另一種類型的異常被拋出?嘗試添加一個catch(...)。

0

我注意到有時候cerr會變成werid,你有沒有嘗試用cout替換cerr?也可以嘗試在異常塊中放置兩個cout。

0

如果沒有輸出正在生成,並且函數返回true。

然後func1()沒有例外。
因此,該函數返回true。

但是,您可能遇到的問題是,在優化代碼(因爲優化程序可能會重新排列代碼)後,除蟲器無法將機器指令映射回C++源代碼。

我建議你嘗試類似下面的東西,以確保你報告的所有例外。

試試這個:

bool func2() 
{ 
    try 
    { 
     func1(); 
    } 
    catch(MyException const& e) 
    { 
     std::cerr << "Error!: Cought My Exception\n"; 
     return false; 
    } 
    catch(...) // Catch any other exceptions 
    { 
     std::cerr << "Error!: Unknown Exception detected\n"; 
     /* 
     * To keep the same functionality of your original code 
     * Rethrow the unknown exception. 
     */ 
     throw; 
    } 
    return true; 
}