Is re-throwing an exception legal in a nested 'try'?
Is the following well-defined in C++, or not? I am forced to 'convert' exceptions to return codes (the API in question is used by many C users, so I need to make sure all C++ exceptions are caught & handled before control is returned to the caller).
enum ErrorCode {…};
ErrorCode dispatcher() {
try {
throw;
}
catch (std::bad_alloc&)开发者_如何学编程 {
return ErrorCode_OutOfMemory;
}
catch (std::logic_error&) {
return ErrorCode_LogicError;
}
catch (myownstdexcderivedclass&) {
return ErrorCode_42;
}
catch(...) {
return ErrorCode_UnknownWeWillAllDie;
}
}
ErrorCode apifunc() {
try {
// foo() might throw anything
foo();
}
catch(...) {
// dispatcher rethrows the exception and does fine-grained handling
return dispatcher();
}
return ErrorCode_Fine;
}
ErrorCode apifunc2() {
try {
// bar() might throw anything
bar();
}
catch(...) {
return dispatcher();
}
return ErrorCode_Fine;
}
I hope the sample shows my intention. My guess is that this is undefined behaviour, but I'm not sure. Please provide quotes from the standard, if applicable. Alternative approaches are appreciated as well.
Thanks!
That's fine. The exception is active until it's caught, where it becomes inactive. But it lives until the scope of the handler ends. From the standard, emphasis mine:
§15.1/4: The memory for the temporary copy of the exception being thrown is allocated in an unspecified way, except as noted in 3.7.4.1. The temporary persists as long as there is a handler being executed for that exception.
That is:
catch(...)
{ // <--
/* ... */
} // <--
Between those arrows, you can re-throw the exception. Only when the handlers scope ends does the exception cease to exist.
Keep in mind if you call dispatch
without an active exception, terminate
will be called. If dispatch
throws an exception in one if it's handlers, that exception will begin to propagate. More information in a related question.
Since dispatcher
called in the catch block throw
will rethrow exception. If you will call dispatcher
outside catch block then terminate()
will be called (according to 15.1/8). There is no undefined behavior in any case.
精彩评论