2013-10-24 23 views
17

我正在用C++編寫程序。該程序一直在爲Win32(x86)正常工作,最近我試圖編譯它原生的x64。當然,東西沒有馬上工作。MSVC x64中的C++異常「跳過」Try-Catch子句

調試問題後,我設法與這個簡單的代碼片段重現它:

class MyException { }; 

int main() 
{ 
    try { 
     for (;;) { 
      try { 
       std::cout << "Throwing" << std::endl; 

       throw MyException(); 

       if (1 == 0) { 
        continue; 
       } 
      } catch (const MyException&) { 
       std::cout << "Catch 1" << std::endl; 
      } 
     } 
    } catch (const MyException&) { 
     std::cout << "Catch 2" << std::endl; 
    } 

    std::cout << "Done" << std::endl; 

    return 0; 
} 

(我會解釋很快if (1==0)條款)

編譯時使用MSVC此代碼x86(我用過2010),結果如預期:

Throwing 
Catch 1 
Throwing 
Catch 1 
Throwing 
Catch 1 
Throwing 
Catch 1 
... 

等等,在一個無限循環。

然而,在編制用於基於x64的結果驗證碼:

Throwing 
Catch 2 
Done 

例外完全跳過內catch子句!

這隻發生在我的代碼中存在if (1 ==0)子句時。當我刪除它時,異常將按預期捕捉到「Catch 1」。

我用其他的編譯器嘗試:

  • 此錯誤也如預期發生在2012年VS
  • 的MinGW和MinGW-W64的工作。

我的問題:這是一個MSVC錯誤,或者這是一些未定義的行爲在C++我失蹤了? 如果這確實是一個MSVC錯誤,我很樂意聽到關於原因的一些見解。

謝謝。

+3

幾乎可以肯定是編譯器錯誤,如果你在文件MS連接錯誤報告(你可以鏈接這個問題),並離開這裏的鏈接,那麼我會給予好評的。很高興看到微軟工程師對此有何評論。 –

+3

很好找!我剛剛走了。首先,它在64位發行版上崩潰鏈接器。其次,我可以用「繼續」來重現它。圍繞它的'if'語句是不必要的。使用VS2012更新3. – Steve

+1

我已經在[MS Connect]上打開了一個錯誤報告(https://connect.microsoft.com/VisualStudio/feedback/details/806490/c-exception-skips-try-catch-clause-in -msvc-x64)的。 –

回答

0

試着開關/ FAS開關:

http://msdn.microsoft.com/en-us/library/367y26c6%28v=vs.80%29.ASPX

某處在你的 「編譯器設置」, 「額外的輸出文件」。 (確保所有其他設置相同)

然後,在兩個輸出之間做一個差異。在這裏發佈差異。我相信有些人可以告訴你爲什麼和如何,也許有些編譯器設置或代碼解決方法。

1

此錯誤可能與編譯器優化有關 - 有趣的是,鏈接器在您的發佈版本中崩潰(當理論上開啓完全優化時)。

您的調試版本是否將優化完全禁用(/ Od)?

Visual Studio Help還包含一個聲明(在「Optimization Best Practices」之下),阻止64位代碼中的try/catch塊。

如果關閉發佈版本中的優化,鏈接器不會崩潰。如果只刪除「continue」語句,它也不會崩潰(但會重現不良行爲)。

if (1==0) { 
//continue; 
}