2012-09-01 31 views
1

以下方法(在Visual Studio 2008 ref類中)包含一個我認爲會被捕獲的簡單錯誤 - 但相反它會導致進程中止「Debug Assertion Failed!」。消息框(msg包含有問題的STL向量src行#)。無論是以調試模式還是發佈模式編譯,都會發生這種情況這種情況下的過程是Excel.exe,並且該方法通過COM interop訪問。未捕獲到Visual C++/STL異常

有人能告訴我爲什麼這個錯誤不會被困住嗎?

String^ FOO() 
    { 
     try { 
      std::vector<int> vfoo; 
      vfoo.push_back(999); 
      return vfoo[1].ToString(); //!!!! error: index 1 not valid 
     } 
     catch(std::exception& stdE) { // not catching 
      return "Unhandled STL exception"; 
     } 
     catch(System::Exception^ E) { // not catching 
      return "Unhandled .NET exception: " + E->Message; 
     } 
     catch(...) { // not even this is catching 
      return "Unhandled exception"; 
     } 
    } 
+0

'vfoo [0] .ToString();'........... – perilbrain

回答

4

在Debug配置中,您將得到一個由迭代器調試功能啓用的斷言。旨在幫助您在使用標準C++庫時發現錯誤。您可以使用Call Stack窗口追溯到觸發斷言的代碼中的語句。該功能由_HAS_ITERATOR_DEBUGGING宏控制,在調試版本中關閉該功能的原因很少。好吧,沒有。

在Release配置中,您將運行Checked Iterators功能,這是在VS2005中引入的安全CRT庫程序的一部分,由_SECURE_SCL宏控制。它有一個內置的鉤子讓調試器停止,就像上面一樣,告訴你它爲什麼會被轟炸。但不是沒有調試器,如果沒有連接,它會立即終止您的程序與SEH異常代碼0xc0000417。這種情況在buck停止的地方,CRT的DLL版本使用_SECURE_SCL生效,並且在編寫託管代碼時,您沒有選擇不使用該DLL的選項。需要使用/ MT進行構建才能完全關閉它,而在C++/CLI中這是不可能的。

這傾向於驅使C++程序員變得非常瘋狂,catch(...){}是一種有福的語言功能,即使恢復程序狀態的機率非常接近零。但是有一個後門(總是有一個後門),參數驗證代碼通過函數指針發出錯誤條件。默認處理程序立即中止程序,但無法捕捉程序,即使使用SetUnhandledExceptionFilter()也不行。您可以使用_set_invalid_parameter_handler()函數替換處理程序。這需要通過你的Main()方法,事情就像這樣:

#include "stdafx.h" 
#include <stdlib.h> 

using namespace System; 

#pragma managed(push, off) 
void no_invalid_parameter_exit(const wchar_t * expression, const wchar_t * function, 
           const wchar_t * file, unsigned int line, uintptr_t pReserved) { 
    throw new std::invalid_argument("invalid argument"); 
} 
#pragma managed(pop) 

int main(array<System::String ^> ^args) 
{ 
    _set_invalid_parameter_handler(no_invalid_parameter_exit); 
    // etc... 
} 

這將運行catch處理器之一。管理的一個,沒有像樣的麪包屑來顯示發生了什麼,但這對於本機C++異常是正常的。

+0

謝謝 - 這是有價值的信息 - 不容易找到。但是,這是一個由Excel加載的DLL - Asserts導致Excel崩潰(!),所以我很驚訝沒有簡單的方法來關閉它們(並且我不想擺弄main(或者dll main這個例子 - 我猜)。幸運的是,.NET部分是一個很薄的層,很容易編碼(例如消除不安全的[索引]查找)。 – tpascale

0

「Debug Assertion Failed!」(調試斷言失敗!聽起來像是一個assert()式的檢查。這些都不是例外。

我實際上使用assert()樣式檢查構成編程錯誤的所有內容,併爲運行時錯誤使用異常。也許微軟也遵循類似的政策; 「索引越界」顯然是編程錯誤,而不是由例如你的磁盤變滿了。