Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Losing exception type when rethrowing an exception from a catch block

Today I found a bug in a catch block:

catch (const exception& e){
    // do something
    // throw e; <-- bug!
    throw;    // <-- right thing to do
}

Basically if I rethrow the exception e explicitly, I get a new std::exception reconstructed, in fact the message from the what() method was the default std::string, instead of my custom built message.

What is the explanation? I thought that throw; is only a shorthand of throw ExceptionJustCaught;.

like image 817
Lorenzo Pistone Avatar asked Sep 22 '12 21:09

Lorenzo Pistone


People also ask

What is Rethrowing exception in Java?

Core Java bootcamp program with Hands on practice Sometimes we may need to rethrow an exception in Java. If a catch block cannot handle the particular exception it has caught, we can rethrow the exception. The rethrow expression causes the originally thrown object to be rethrown.

What happens if catch block throws exception?

Q #3) What happens when a catch block throws an exception? Answer: When an exception is thrown in the catch block, then the program will stop the execution. In case the program has to continue, then there has to be a separate try-catch block to handle the exception raised in the catch block.

Can you Rethrow an exception?

If a catch block cannot handle the particular exception it has caught, you can rethrow the exception. The rethrow expression ( throw without assignment_expression) causes the originally thrown object to be rethrown.

Can I catch and throw the same exception in Java?

The throw keyword in Java is used to explicitly throw either a custom-made exception or in-built exception. But sometimes in the catch block, we need to throw the same exception again. This leads to re-throwing an exception.


2 Answers

Exception objects are a bit special. They're constructed in a special place in memory, and their lifetime is determined by the catch block in which they're caught.

If you say throw e;, the lifetime of the original exception ends at the end of the catch block, and you are throwing a new exception by copying e, thus producing a classical slicing problem: Since e is a polymorphic reference to an object whose dynamical type is usually more-derived than std::exception, you end up slicing off the derived part of the object.

By contrast, throw; is a special statement that reactivates the original exception, so that it is no longer caught, and its lifetime does not end at the end of the block anymore. In fact, if you catch by non-constant reference, you can keep modifying the exception object and rethrow and thus communicate a state change up the lower catch blocks. But bear in mind that rethrowning is different from throwing a new exception!

like image 181
Kerrek SB Avatar answered Sep 28 '22 11:09

Kerrek SB


Just a throw throws the current exception by reference. throw e copy constructs a new exception to throw. This is much the same way return works.

like image 37
David Schwartz Avatar answered Sep 28 '22 10:09

David Schwartz