2011-02-03 83 views
10

的類型,說我有:C++ - 尋找陷入默認異常

try 
{ 
externalLibrary::doSomething(); 
} 
catch (std::exception &e) 
{ 
//yay I know what to do 
} 
catch (...) 
{ 
//darn, I've no idea what happened! 
} 

有可能是你會得到一個異常的情況下,你不知道它的來自或爲什麼 - 在一些外部庫沒有調試信息。有沒有辦法找到拋出的東西或以其他方式獲取與其相關的數據?他們可能做:

throw myStupidCustomString("here is some really useful information"); 

但我永遠不會知道,如果我趕上...

在MSVC++ 2008,如果它很重要的工作。

回答

6

因爲C++是靜態類型的,所以你必須捕獲一個已知類型。但是,您可以調用一個外部函數(或一組函數)來處理在您調用它們時未知的異常類型。如果這些處理程序都具有已知類型,則可以註冊它們以進行動態嘗試。

struct myStupidCustomString { 
    myStupidCustomString(char const *what) : what (what) {} 
    char const *what; 
}; 

void throws() { 
    throw myStupidCustomString("here is some really useful information"); 
} 

// The external library can provide a function, or you can provide a wrapper, which 
// extracts information from "unknown" exception types. 
std::string extract_from_unknown_external_exception() { 
    try { throw; } 
    catch (myStupidCustomString &e) { 
    return e.what; 
    } 
    catch (...) { 
    throw; // Rethrow original exception. 
    } 
} 

Use

void example() { 
    try { throws(); } 
    catch (...) { 
    try { 
     std::string extracted = extract_from_unknown_external_exception(); 
     std::cout << "extracted: " << extracted << '\n'; 
    } 
    catch (...) { 
     // Chain handlers for other types; e.g. exception types from other libraries. 
     // Or do something generic for the unknown exception. 

     // Or rethrow the original unknown exception: 
     throw; 
    } 
    } 
} 

Handler chain

typedef std::string Extract(); 
std::vector<Extract*> chain (1, &extract_from_unknown_external_exception); 
// Chain would normally be initialized using whatever scheme you prefer for 
// initializing global objects. 
// A list or other container (including a manual linked list that doesn't 
// require dynamic allocation) may be more appropriate, depending on how you 
// want to register and unregister handlers. 
std::string process_chain() { 
    for (std::vector<Extract*>::iterator x = chain.begin(); x != chain.end(); ++x) { 
    try { 
     return (*x)(); 
    } 
    catch (...) {} // That handler couldn't handle it. Proceed to next. 
    } 
    throw; // None could handle it, rethrow original exception. 
} 

void example() { 
    try { throws(); } 
    catch (...) { 
    try { 
     std::string extracted = process_chain(); 
     std::cout << "extracted: " << extracted << '\n'; 
    } 
    catch (...) { 
     throw; // Rethrow unknown exception, or otherwise handle it. 
    } 
    } 
} 

最後,如果你知道實現細節,你可以使用這些提取任何額外的信息,請執行會公開。 C++ 0x也以便攜的方式公開了一些細節;看看std :: exception_ptr。

1

你不能在標準的C++。我認爲這樣的例外是非常特殊的,並且通過嘗試記錄你有一個不好的例外的事實來處理它們,然後嘗試退出程序,而你仍然可以。

如果幸運的話,您可以保存任何數據。

2

有沒有辦法知道在C異常的類型++(在catch(...)塊,我的意思是,五言的)

你可能只是希望你知道究竟externalLibrary::doSomething();呢,如果你寫它,或,就像你的情況一樣,你可能只是希望,如果有這樣的話,那麼externalLibrary::doSomething();就有非常好的文檔並閱讀它。所有好的庫都有詳細的文檔。

+0

根據我的經驗,異常的詳細文檔並不像體面的params文檔那樣普遍。但是,如果是這樣,我只需要測試標準的可能性......系統異常呢? – 2011-02-03 11:35:25

+0

你是什麼意思「系統異常呢?」我不知道他們是否可以在C++程序中被捕獲:?此外,我使用的大多數庫都有自己的異常層次結構,並且有很好的文檔記錄。但是,當然,這並不意味着所有圖書館都有這樣的事情。另外,如果它是C庫,你知道,沒有例外拋出。 – 2011-02-03 11:40:11

+0

我的意思是,沒有特殊的方法來捕捉像null-ptr訪問,div/0之類的東西嗎?我認爲有方法可以在第三方庫存在bug的情況下捕獲這些問題? – 2011-02-03 14:36:43

15

如果您使用gcc或CLANG,則可以使用技巧來了解「未知」異常類型。請記住,這是非標準的!

#include <cstdlib> 
#include <iostream> 
#include <cxxabi.h> 


using namespace __cxxabiv1; 

std::string util_demangle(std::string to_demangle) 
{ 
    int status = 0; 
    char * buff = __cxxabiv1::__cxa_demangle(to_demangle.c_str(), NULL, NULL, &status); 
    std::string demangled = buff; 
    std::free(buff); 
    return demangled; 
} 

struct MyCustomClass 
{}; 

int main(int argc, char * argv[]) 
{ 
    try 
    { 
     throw MyCustomClass(); 
    } 
    catch(...) 
    { 
     std::cout << "\nUnknown exception type: '" << util_demangle(__cxa_current_exception_type()->name()) << "'" << std::endl; 
    } 
    return(0); 
}