在g++
和clang++
(至少在Linux中),抛出异常并且没有捕获(未捕获的异常)后会显示以下典型消息:
terminate called after throwing an instance of 'std::runtime_error'
what(): Bye
例如:
#include<stdexcept>
int main(){
throw std::runtime_error("Bye");
}
如何在完全访问抛出的异常的同时自定义错误消息?
文档(http://www.cplusplus.com/reference/exception/set_unexpected/)提及set_unexpected
(和set_terminate
),但我不知道unexpected_handle
如何实际访问被抛出的异常,例如拨打e.what()
或其他内容。
注意:这背后的原因是我想为更复杂的异常类层次结构自定义消息,该层次结构具有比简单what()
更多的信息,并且我想显示它抛出此类型异常(但如果抛出一个简单的std::exception&
,则默认值与典型值相同。
Note2 :根据目前为止的两条建议,“通过捕获异常来定制未捕获的异常”。看起来像代码中的内容。我想知道是否有办法做同样的事情而不向我写的所有 try-catch
代码添加main()
块。
#include<stdexcept>
int main() try{
....
}catch(std::exception& e){
std::clog << "terminate called after throwing an instance of '" << typeid(e) << "'\n"
<< " what(): " << e.what() << '\n'
<< "otherinfo, like current time\n";
}catch(alternative_exception& e){
std::clog << "terminate called after throwing an instance of '" << typeid(e) << "'\n"
<< " what(): " << e.what() << '\n'
<< " where(): " << e.where() << '\n'
<< " how(): " << e.how() << '\n'
<< "othermember(): " << e.othermember() << '\n';
}
答案 0 :(得分:3)
用于自定义未捕获异常处理的钩子正在捕获异常。
答案 1 :(得分:3)
根据@JonPurdy(接受)的回答,我尝试了这个似乎有效的代码,至少在Linux中使用gcc 4.7.2和clang 3.2。我不知道它有多强大或可移植(欢迎评论),我尽量不对默认的终止处理程序做出假设:
#include<stdexcept>
#include<iostream>
#include<typeinfo> // for typeid
// a special exception, can be an abstract class, here it is concrete class to make the example shorter.
struct debug_exception : std::runtime_error{
std::string where_;
debug_exception(std::string what, std::string where) : std::runtime_error(what), where_(where){}
virtual const char* where() const{return where_.c_str();}
};
std::terminate_handler my_default_terminate;
void my_verbose_terminate_handler(){
try{
throw;
}catch(debug_exception& e){
std::cerr << "my_verbose_terminate_handler called after throwing an instance of "
<< typeid(e).name() << std::endl; // or demangled
std::cerr << " what(): " << e.what() << std::endl;
std::cerr << " where(): " << e.where() << std::endl;
}catch(...){
my_default_terminate(); // probably __gnu_cxx::__verbose_terminate_handler();
}
}
std::terminate_handler my_improve_terminate(){
my_default_terminate = std::set_terminate(my_verbose_terminate_handler);
return my_default_terminate;
}
int main(){
my_improve_terminate();
// throw 2; // says the default "terminate called after throwing an instance of 'int'"
// throw std::runtime_error("bye"); // says the default "terminate called ... what(): bye"
throw debug_exception("Bye", __PRETTY_FUNCTION__); // says my_verbose_terminate_handler called ... what(): Bye, where(): int main()"
}
现在我正在尝试将所有代码包装在class
中并在my_improve_terminate()
之前调用main
,因此当包含某个文件时,它将成为新的默认值。
答案 2 :(得分:2)
除了实际捕捉你关心的例外之外,std::set_terminate()
和std::current_exception()
(C ++ 11)应该足以做一些有趣的事情。