views:

66

answers:

2

If I have a code like the following:

try {
  doSomething();
} catch (...) {
  noteError();
}

void noteError() {
  try {
    throw;
  } catch (std::exception &err) {
    std::cerr << "Note known error here: " << err.what();
  } catch (...) {
    std::cerr << "Note unknown error here.";
  }
  throw;
}

Will the original exceptions get thrown from both places inside the lower frame of noteError()?

+5  A: 

Your original code was fine. You caught different exception types and called a function that would log a message and rethrow. The throw statement is not required to appear directly inside the corresponding catch block. If you call one of those "note" functions and you're not currently handling an exception, though, then your program will call terminate().

Your new code is also fine. It's OK to catch everything and then call another function that rethrows to go to a more specific handler. That's the exception dispatcher idiom described in the C++ FAQ. It looks a little peculiar to rethrow the exception after the dispatching block has finished, but if that same throw statement had occurred after noteError returned (inside the original catch block) instead of where it is now, then it would be perfectly ordinary; it's demonstrated in the standard, §15.1/6.

Rob Kennedy
+1 for the 'terminate' perspective
Chubsdad
+2  A: 

The wording in the standard (§15.1/2) is (emphasis mine):

When an exception is thrown, control is transferred to the nearest handler with a matching type (15.3); “nearest” means the handler for which the compound-statement, ctor-initializer, or function-body following the try keyword was most recently entered by the thread of control and not yet exited.

When has a try block "exited"? According to the grammar (§15/1), try blocks end with a sequence of handlers, so the block ends when the last handler ends. In other words:

try // <- start of try block
{
}
catch (whatever) // <- first handler
{
}
// ... more handlers
catch (whatever_again) // <- last handler
{
} // <- end of try block

So yes, your code is fine. When re-thrown, the nearest try block has a matching handler (namely catch (...)), so that handler is entered.

GMan
@GMan I've extended the question in a way which I still think works, but could you please confirm that a second throw will also work.
WilliamKF
@William: As soon as you put a semicolon after `throw`. :) [This question](http://stackoverflow.com/questions/2474429/does-throw-inside-a-catch-ellipsis-rethrow-the-original-error/2474436#2474436) might be of interest.
GMan
@GMan Oops, semi-colon now added.
WilliamKF