Does this code
try
{
opaque_function_that_might_throw_arbitrary_exception ();
}
catch (...)
{
throw;
}
differ in any way semantically from just calling
opaque_function_that_might_throw_arbitrary_exception ();
in C++? Are there differences between the standards?
I though both snippets would be semantically identical, but I checked with the compiler-explorer and it generates different code, even on the highest optimization level. This made me wonder if there is something I'm missing.
Yes, there is a subtle difference in one particular place. Consider this main function:
int main() {
RAIIHandle important_resource{ /*...*/ };
opaque_function_that_might_throw_arbitrary_exception ();
}
Is important_resource
freed upon an exception being thrwon? Well, it's implementation defined. std::terminate
is called, but the stack may not be unwound if an exception escapes from main
. For some resources, this could spell real trouble.
Now in this case:
int main() {
try {
RAIIHandle important_resource{ /*...*/ };
opaque_function_that_might_throw_arbitrary_exception ();
}
catch(...) {
throw;
}
}
std::terminate
is still called. But not before a suitable handler is found for the exception. The stack must be unwound. So our important_resource
is definitely freed.