2009-06-28 156 views
4

有什麼辦法可以在這裏獲得至少一些信息嗎?有什麼方法可以獲得一些信息,至少可以捕獲(...)嗎?

... 
catch(...) 
{ 
    std::cerr << "Unhandled exception" << std::endl; 
} 

我有這個作爲圍繞我所有代碼的最後一招。讓它崩潰會更好嗎,因爲那麼我至少可以得到崩潰報告?

+7

注意GCC具有標題cxxabi.h,其中包含一個__cxa_current_exception_type();返回一個std :: type_info對象的extern「C」函數和一個demangles的__cxa_demangle。使用http://www.codesourcery.com/public/cxx-abi/abi.html中指定的這兩個函數,您可以打印GCC上的例外類型。 – 2009-06-28 17:49:06

回答

9

不,沒有任何辦法。嘗試讓所有異常類從一個類中派生出來,如std::exception,然後捕獲那個類。

但是,您可以重新嵌套try,試圖找出類型。但是,你可以使用先前的catch語句(並且只有在回退時才使用...)。

1

是有,但如何有用它是公開辯論:

#include <exception> 
#include <iostream> 
using namespace std; 

int f() { 
    throw "message"; 
} 

int main() { 
    try { 
     f(); 
    } 
    catch (...) { 
     try { 
      throw; 
     } 
     catch(const char * s) { 
      cout << "caught " << s << endl; 
     } 
    } 
} 

而實際上回答你的問題,恕我直言,你總是應該在 頂層有一個catch(...)的代碼,在您的應用程序中出現意外異常時以應用程序手冊完全記錄的方式終止(或以其他方式處理)。

+0

但這並沒有拋出7 – 2009-06-28 17:23:22

0

我相信你應該 catch(...),如果你有一個合理的行動在那一點,並希望應用程序繼續運行。

爲了生成崩潰報告,您不必崩潰,請介意。有用於生成小型轉儲的API,您可以在SEH處理程序中執行此操作。

4

你可以使用gdb或其他調試器來做到這一點。當任何異常拋出時,告訴調試器停止(在gdb中,命令是歡快的catch throw)。然後,您將看到不僅是例外的類型,而且它確切地來自哪裏。

另一個想法是註釋掉catch (...),讓你的運行終止應用程序,並希望告訴你更多關於異常。

一旦你找出例外的是什麼,你應該嘗試更換或東西,它從std::exception得到增強它。不得不catch (...)不是很好。

如果使用GCC或鏘你也可以嘗試__cxa_current_exception_type()->name()來獲得當前的異常類型的名稱。

0

這是我在一個項目中使用的方法。它涉及到重新拋出的異常類型與已知的例外列表匹配,然後在調度匹配一些行動(在這種情況下,只是將一些字符串信息,但它也可以調用一個函數註冊的對象)。

如果你希望這個想法可以擴展到異常類型的動態登記,你必須要小心的是,以確保該列表是在大多數衍生到最小派生順序的東西(需要很多在註冊期間重新投擲和捕捉!)

#include <iostream> 
#include <stdexcept> 
#include <exception> 
#include <typeinfo> 
#include <system_error> 

namespace detail { 
    // a function which compares the current exception against a list of exception types terminated 
    // with a void type 
    // if a match is made, return the exception (mangled) class name and the what() string. 
    // note that base classes will be caught if the actual class is not mentioned in the list 
    // and the list must be in the order of most-derived to least derived 
    // 
    template<class E, class...Rest> 
    std::string catcher_impl() 
    { 
     try 
     { 
      std::rethrow_exception(std::current_exception()); 
     } 
     catch(const E& e) 
     { 
      bool is_exact = typeid(E) == typeid(e); 
      return std::string(typeid(E).name()) + (is_exact ? "(exact)" : "(base class)") + " : " + e.what(); 
     } 
     catch(...) 
     { 
      return catcher_impl<Rest...>(); 
     } 
     return "unknown"; 
    } 

    // specialise for end of list condition 
    template<> std::string catcher_impl<void>() 
    { 
     return "unknown exception"; 
    } 
} 

// catcher interface 
template<class...Es> 
std::string catcher() 
{ 
    return detail::catcher_impl<Es..., void>(); 
} 

// throw some exception type 
// and then attempt to identify it using the type list available 
// 
template<class E> 
void test(E&& ex) 
{ 
    try 
    { 
     throw std::forward<E>(ex); 
    } 
    catch(...) 
    { 
     std::cout << "exception is: " 
     << catcher<std::invalid_argument, std::system_error, std::runtime_error, std::logic_error>() 
     << std::endl; 
    } 
} 

int main() 
{ 
    test(std::runtime_error("hello world")); 
    test(std::logic_error("my logic error")); 
    test(std::system_error(std::make_error_code(std::errc::filename_too_long))); 
    test(std::invalid_argument("i don't like arguments")); 

    struct my_runtime_error : std::runtime_error 
    { 
     using std::runtime_error::runtime_error; 
    }; 
    test(my_runtime_error("an unlisted error")); 
} 

示例輸出:

exception is: St13runtime_error(exact) : hello world 
exception is: St11logic_error(exact) : my logic error 
exception is: NSt3__112system_errorE(exact) : File name too long 
exception is: St16invalid_argument(exact) : i don't like arguments 
exception is: St13runtime_error(base class) : an unlisted error 
相關問題