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.
Output:
my_unexpected called
bad_exception
func called
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
Comments
Moral #1 Never write an exception specification
Moral #2: Except possibly an empty one, but if I were you I’d avoid even that.
Ivan