2009-06-28 147 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 
相关问题