有没有办法在这里获得至少一些信息?
...
catch(...)
{
std::cerr << "Unhandled exception" << std::endl;
}
我将这作为我所有代码的最后手段。让它崩溃会更好吗,因为那时我至少可以得到崩溃报告?
答案 0 :(得分:9)
不,没有办法。尝试使所有异常类派生自一个类,如std::exception
,然后捕获那个。
但是,您可以重新抛出嵌套的try
,以试图找出类型。但是你可以使用之前的catch子句(并且 ...
仅作为后退)。
答案 1 :(得分:4)
您可以使用gdb或其他调试器执行此操作。告诉调试器在抛出任何异常时停止(在gdb中,命令是热闹的catch throw
)。然后,您不仅会看到异常的类型,还会看到它的确切位置。
另一个想法是注释掉catch (...)
并让你的运行时终止你的应用程序,并希望告诉你更多关于异常的信息。
一旦你弄清楚异常是什么,你应该尝试用从std::exception
派生的东西替换或扩充它。完全不得不catch (...)
。
如果您使用GCC或Clang,您还可以尝试__cxa_current_exception_type()->name()
获取当前例外类型的名称。
答案 2 :(得分: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;
}
}
}
实际上要回答你的问题,恕我直言,你应该总是有一个问题(...) 代码的顶级,当您的应用程序中出现意外异常时,以应用程序手册完整记录的方式终止(或以其他方式处理)。
答案 3 :(得分:0)
我相信你应该捕获(...),如果你在这一点上有一个合理的行动方案并希望应用程序继续运行。
请注意,您不必为了生成崩溃报告而崩溃。有用于生成小型转储的API,您可以在SEH处理程序中执行此操作。
答案 4 :(得分: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