Use of std::bad_exception
std::bad_exception is a useful device to handle unexpected exceptions in a C++ program , which works in conjunction with unexpected_handler. unexpected_handler and terminate_handler are a traditional way of dealing with unknown exceptions. std::set_unexpected () and std::set_terminate () functions let us register custom handlers instead of standard handlers, which usually abort the program. More information can be found here.Assuming g++ 4.0.2 complies with the standard in this area, I verified that if function f() throws an exception that is not listed in its exception specification list, our custom function pointed to by the unexpected_handler is invoked if we have set one. If our custom handler rethrows whatever unknown exception caused the unexpected() to be invoked, following things happen.
* If the exception specification of f() included the class std::bad_exception, unexpected() will throw an object of type std::bad_exception, and the C++ run time will search for another handler at the call of f(). So basically, you have an opportunity to translate the unknown exception into a std::bad_exception from within your custom handler by simply rethrowing. This is useful because now you can catch std::bad_exception and can print meaningful diagnostic message. I also saw that uncaught_exception() returns false.
* If the exception specification of f() did not include the class std::bad_exception, the function terminate() is called. You can of course set a terminate handler but you have to terminate the program from this point onwards because C++ runtime will terminate it anyways!
A simple program can make this a lot clear.
void my_unexpected () { if (!std::uncaught_exception()) std::cerr << "my_unexpected called\n"; throw; } void my_terminate () { std::cerr << "my_terminate called\n"; } void func () { std::cerr << "func called\n"; } void g () throw (std::bad_exception, int) { throw 1.0; // throws double } int main (void) { std::set_unexpected (my_unexpected); std::set_terminate (my_terminate); atexit (func); try { g(); } catch (int) { std::cerr << "caught int\n"; } catch (std::bad_exception e) { std::cerr << "bad_exception \n"; } return 0; }
Output:
my_unexpected called
bad_exception
func called