Tony Johansson wrote:
Hello Experts!
Assume foo is a method in a some class or a stand-alone function and method
push is throwing an exception of class logic_error.
Assume also that I want to handle this exception in foo if it's possible.
This will cause a problem because C++ doesn't have the finally keyword and I
can't do delete both in the exception handler and after the exception
handler that's because I have put in the throw to throw it further
to let some other method to handle it. But if I remove this throw how is it
then possible to get a
solution that will hold and i a good solution. If I just remove this throw
and an exception occurs will this cause delete s two times and resuting in
undefined behaviour.
void foo()
{
IntStack* s;
Note that s is uninitialized - could contain garbage.
try
{
s = new IntStack(20);
new can throw badalloc - s may not get set - still contains garbage. s->push(20);
}
catch(const logic_error& e)
{
delete s;
throw; //
}
delete s;
Trying to delete garbage. Not good 10 out of 10.
Another problem, is if push throws some other (possibly future)
exception type, you will leak s.
}
To answer the OP question, I would use the RAII idion (Resource
Aquisition Is Initialization) and remove the need to handle this type of
logic manually.
#include <list>
#include <memory>
typedef std::list<int> IntStack;
struct logic_error {};
void foo()
{
std::auto_ptr<IntStack> s;
try
{
s.reset( new IntStack(20) );
s->push_back(20);
}
catch(const logic_error& e)
{
throw; //
}
}
OK - so you don't like that ? This will work too. Although, the code
above looks alot simpler and much more intuitive.
void foo()
{
IntStack* s = 0;
try
{
try
{
s = new IntStack(20);
s->push(20);
}
catch(const logic_error& e)
{
delete s;
s = 0;
if ( cant_fix_logic )
{
throw; //
}
}
} catch (...)
{
delete s;
throw;
}
delete s;
}