2011-08-03 75 views
7

我遇到了一些我繼承的代碼的情況......老實說,我相信代碼是正確編寫的,但是這個錯誤似乎仍然表現出來。試着抓住不按預期工作

我會很快注意到,代碼是從Linux交叉編譯到LynxOS,我不確定這是否與錯誤有關。

基本上,在一個特定的情況下:

try { 
    std::vector<ClassA> x = SomeGeneratingFunction(); 

    //We get to here fine. X may be empty/unpopulated though. 
    if (x.size() < 1) 
    { 
     throw(MyException("It crashed.")); 
    } 
} 
catch (MyException e) 
{ 
    //Handle it. 
} 
catch (...) 
{ 
    //Handle it. 
} 

我們拋出給出的載體是無人居住的,但由於某些原因,罰球繞過catch子句 - 他們兩個。它似乎只發生在這裏 - 雖然我們通常不會形成一個if語句範圍,但是它應該完全不相關,因爲它仍然處於嘗試範圍之內。

PS:下面的代碼實際上是一個函數的內容,即使它們應該全部由catch塊處理,異常也會在函數調用時出來。

任何想法這可能嗎?是的,這不是真正的代碼/異常類,但異常類是你重載std :: exception的簡單例子,SomeGeneratingFunction()確實返回一個好的向量,即使它是空的。我無法提供真實的代碼,但是這是非常接近的,除非我可能把我寫下來的任何小拼寫錯誤寫出來。

感謝您提前提出任何想法!

-w00te

+0

如果添加調試語句(在條件之前,拋出之前和之後)它會改變行爲嗎?如果你從圖片中取出矢量怎麼辦? GDB在用「catch throw」運行時會做什麼?你如何編譯?嘗試使用優化標誌 – nhed

+0

按預期方式打印調試語句,但不會改變行爲。這是一個龐大的系統,它具有複雜的分層結構,並且在不同的部分使用了大量的標誌 - 但更重要的是,我們在任何你應該(或嘗試)的地方使用嘗試捕獲,並且之前沒有看到過這種情況。我想也許交叉編譯器可能會對範圍或類似的東西造成混亂,但我對編譯器知之甚少。我有幾個人看過去 - 我們可以通過做,而不是如果/拋出來解決它,但它是令人擔憂的是解決一些事情,不應該發生 –

+2

我不知道,但可以考慮寫漁線作爲這* catch(const MyException&e)*可以避免爲MyException拷貝構造函數付費,因爲你會得到一個* throw *拋出的拷貝。 –

回答

0

我會重寫它,而不使用try/catch。無論如何,在這裏使用try/catch似乎不太合適。就你所知,異常可能無法在你的目標平臺上運行。

+0

這就是我所做的,但我想了解它們有什麼問題,因爲它們在很多其他地方使用,而且看起來工作正常 - 其他代碼可能需要調整。 –

+0

這不是我的問題的解決方案,但它最終必須做的事情,所以我會標記它,哈哈。用信息標記其他答案我也發現有幫助。 –

0
catch (MyException e) 

應改爲:

catch (const MyException &e) 

我不知道爲什麼你的罰球看起來像一個函數或者,那種怪異。

編輯:

我已經與基於類似的漁獲物的問題,雖然我同意,這不是在這種情況下,玩具足夠。

編譯看起來對我而言,是Try定義爲有趣的東西?如果它是空的,可能是有意義的,如果你的編譯器忽略catch語句而沒有嘗試。

+8

這可能是個好建議,但這不是問題。 –

+0

這樣做不僅僅是通過停止形成副本來提高效率嗎?還是說,如果沒有它,實際上是否會將原始異常傳播出去? –

+2

如果'MyException'不可複製(儘管編譯器可能需要爲此發佈診斷),這個_could_會成爲問題,但我認爲這是不太可能的。 (哦,用'const'引用捕獲更好。) – sbi

1

由於throw語句中的異常對象周圍有一組備用括號,因此它看起來像一個函數調用。是否有可能定義了一個名爲throw的函數?異常構造函數的參數使它不會成爲Most Vexing Parse的受害者,但如果實際代碼與示例不同,那麼這是可能的。

+0

'throw'是一個關鍵字,你不能用這個名字來定義一個函數。 – interjay

+0

'throw MyException()'或'throw(MyException())'不可能是令人煩惱的解析,因爲throw是關鍵字,而不是類型名稱。我不知道任何C++編譯器,如果您嘗試使用'throw'作爲函數的名稱,則不會投訴。 –

+0

@interjay我想過,但也許有一些不正常的情況,'throw'是由宏重新定義的?我同意這種說法,但絕望的問題需要絕望的解決方案。 –

-2

讓我們來解決這個問題......除非你想讓程序崩潰,否則不要在C++中使用異常。我知道異常可能相當有用,但它們的性能很差,因爲它引發了操作系統內核捕獲的硬件異常。使用返回值和錯誤代碼可能比拋出異常和捕獲異常快500倍。

+9

-1。完全廢話。 –

+0

爲什麼?這是一個設計建議。我做了基準測試以驗證我的團隊的另一位程序員確實查看了生成的程序集以瞭解異常機制。我們發現的結果可能令人驚訝,但問題嚴重。 – neodelphi

+0

http://stackoverflow.com/questions/307610/how-do-exceptions-work-behind-the-scenes-in-c –

9

由於catch (...)子句沒有發現異常,我的回答並沒有解決OP的問題。但對於那些在SO上發現這個問題的人,也許我的回答很有用,因爲這解釋了爲什麼第一次捕獲失敗。

我有一個類似的問題,我的catch(const std::exception& ex)只是不工作。事實證明,這是一個愚蠢的問題,因爲我在C#和C++異常之間切換,在C#中,當拋出異常時需要指定new,而在C++中通常不需要(但是可以,但在這種情況下你扔一個指針而不是一個參考)。我不小心做

throw new std::runtime_error("foo"); 

所以

catch(std::exception* ex) 

會抓住它,但

catch(std::exception& ex) 

沒有。當然,解決方案只是刪除新的語句,因爲這不是C++中的傳統設計模式。

+0

在我的代碼中出現了完全相同的問題!一直在搜尋很多時間的可能原因,最終結果是你提到的同樣愚蠢的錯誤。 –

0

如果你有功能在一個較小的範圍內MyException(甚至可能是偶然,最令人頭痛的解析),那麼throw MyException("It crashed")會調用該函數並引發返回值。