Use of std::bad_exception

11:35:00 PM 0 Comments A+ a-

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