I'm writing a drop-replacement for a container, and I'm trying to
get all the exception-guarantees in place. I'm currently writing
the clear
method, and I want it to complete as much as possible,
and to always leave the container in a consistent state, even if
one of the destructors throw an exception. I also want to rethrow
the exception after I'm done cleaning, preferably without slicing.
This brings me to the question; when is an exception destructed? Lets have a look at one attempt: This is simplified for the example.
void container::clear()
{
bool had_exception = false;
std::exception* exp;
internal_set_empty(); // this cant throw
while( ! internal_done() )
{
try
{
internal_destruct_next(); // this might throw if T::~T() throws
}
catch( std::exception& e )
{
had_exception = true;
exp = &e;
}
}
if( had_exception )
throw *exp;
}
I expect this to fail badly, because the exception is probably destructed when it is considered handled, and this doesn't technically rethrow.
Another attempt would be taking a copy of the exception, something that I expect would slice.
Is there a way to extend the lifetime of the exception so I can rethrow
it later?
If possible, I would also like to be able to rethrow exceptions caught
via catch(...)
.
Throwing an exception out of a destructor is dangerous. If another exception is already propagating the application will terminate.
Exception handling and object destruction in C++ Destructors in C++ basically called when objects will get destroyed and release memory from the system. When an exception is thrown in the class, the destructor is called automatically before the catch block gets executed.
Using destructors Destructors are called when one of the following events occurs: A local (automatic) object with block scope goes out of scope. An object allocated using the new operator is explicitly deallocated using delete . The lifetime of a temporary object ends.
even if one of the destructors throw an exception
Cannot be done. Destructors are nothrow for a reason- you can't recover from a throwing destructor. It's clear that you don't do anything to clean up the objects whose destructor threw- because how could you even try to do that- but that also means that you've just left them hanging around in a zombie state.
On your more specific question, you could use recursion to stay inside the catch's stack frame to try to keep deleting elements, or you could also use std::exception_ptr
and friends in C++11 which are intended for transporting exceptions around.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With