3

So, I'm looking at the C++ reference for the try/catch block.

I see there are a few ways to capture an exception like so:

try { f(); } catch (const std::overflow_error& e) { // this executes if f() throws std::overflow_error (same type rule) } catch (const std::runtime_error& e) { // this executes if f() throws std::underflow_error (base class rule) } catch (const std::exception& e) { // this executes if f() throws std::logic_error (base class rule) } catch (...) { // this executes if f() throws std::string or int or any other unrelated type } 

I see in the following examples that you can capture the "e" data like so:

std::cout << e.what(); 

So my question boils down to this:

How do I get the exception data on the catch(...)?

(Side question: is it even wise to use the catch(...)?)

2
  • 3
    You can't. If you are catching ... this could be anything from an integer to std::string. The only thing you should normally do with ... is log an unknown exception in some logging system and re-throw (so the application terminates). Then debug your code to understand why something so strange was thrown. Commented Oct 31, 2016 at 13:33
  • @LokiAstari Okay, well that makes sense. Thanks :) Commented Oct 31, 2016 at 13:42

2 Answers 2

8

In general, you can not. C++ allows pretty much anything to be thrown. For example throw 42; is perfectly well-defined C++ code, and the exception's type is int.

As for it being wise to use it - there are valid uses:

  • If an exception is thrown and there is no catch block for it all the way up, std::terminate is called and there is no guarantee of stack unwinding. catch(...) guarantees that (because it catches any exception).

int main() { super_important_resource r; may_throw(); // r's destructor is *not* guaranteed to execute if an exception is thrown } 

int main() try { super_important_resource r; may_throw(); // r's destructor is guaranteed to execute during stack unwinding } catch(...) { } 
  • it's a valid use case to log that an exception was thrown, before rethrowing it.

try { //... } catch(...) { log() << "Unknown exception!"; throw; } 
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you krzaq for your answer. This makes sense.
Am I right thinking that problem with stack unwinding with uncaught exception may happens just with resources that were allocated on stack in main() function? While moving all way up from exception point, stack have to be unwinded, at least up to main() function?
3

How do I get the exception data on the catch(...)?

In general case, you cannot get an arbitrary exception. Still, if the exception type is one of known types, you can re-throw current exception and catch it.

Side question: is it even wise to use the catch(...)?)

It makes sense to use at as a fallback option, to handle unexpected exceptions. And one could consider catch-rethrow technique to avoid copy-pasting of catch series in several places.

void Catcher() { try { throw; } catch (const std::overflow_error& e) { // this executes if f() throws std::overflow_error (same type rule) } catch (const std::runtime_error& e) { // this executes if f() throws std::underflow_error (base class rule) } catch (const std::exception& e) { // this executes if f() throws std::logic_error (base class rule) } catch (...) { // oops! } } int main() { try { f(); } catch (...) { Catcher(); } } 

6 Comments

How does this address the OPs question?
@erenon If we are within the catch(...) block, we still can get the exceptions of known types.
@AlexD I like your Catcher class to avoid repetition. Also, thanks for editing your answer to include the additional information. +1
@krzaq .It is how I understood the standard. "The exception with the most recently activated handler that is still active is called the currently handled exception." and "A throw-expression with no operand rethrows the currently handled exception".
@AlexD sure, I just always though that you had to throw it right there in the catch block. So thank you, I learned something new today :) (I also verified it with cppreference, gcc and clang, so you're very unlikely to be wrong on this)
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.