5

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';
}
4

3 回答 3

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()"
}

现在我正在尝试将所有代码包装在 a 中并在之前class调用,因此当包含某个文件时,它成为新的默认值。my_improve_terminate()main

于 2013-06-28T21:05:59.043 回答
3

自定义处理未捕获异常的钩子是捕获异常。

于 2013-06-23T11:49:19.240 回答
2

除了实际捕获您关心的异常之外,std::set_terminate()( std::current_exception()C++11) 应该足以做一些有趣的事情。

于 2013-06-23T20:00:42.490 回答