exception in a constructor

E

ES Kim

It's a common practice that you throw an exception in a constructor
when the invariant of the class is not met. But what if it's combined
with auto_ptr? I mean:

#include <memory>
using namespace std;

struct S
{
S(int i) { if (i < 0) throw "oops"; }
};

int main()
try
{
auto_ptr<S> ap(new S(-1)); // A
}
catch (...)
{
}

Statement A can be considered step by step like this:
(1) raw memory is allocated by ::eek:perator new(sizeof(S))
(2) the memory is initialized by S::S(int)
(3) an auto_ptr is constructed pointing to the memory
But you see an exeption is thrown at step (2) and auto_ptr is
*not* constructed, which means ~auto_ptr is not called.
The net result is memory leak, of course.
What is a proper way to solve this kind of problem?
Let's not consider the possibility of bad_alloc. (If a bad_alloc
is thrown, there's no leak at least.)
 
D

Dietmar Kuehl

ES said:
auto_ptr<S> ap(new S(-1)); // A
Statement A can be considered step by step like this:
(1) raw memory is allocated by ::eek:perator new(sizeof(S))
(2) the memory is initialized by S::S(int)
(3) an auto_ptr is constructed pointing to the memory
But you see an exeption is thrown at step (2) and auto_ptr is
*not* constructed, which means ~auto_ptr is not called.
The net result is memory leak, of course.

The people creating the C++ standard thought of this: if an exception
is thrown during step 2, all members constructed so far are destroyed
and then 'operator delete()' is called appropriately (i.e., if you
used a placement form of new, a corresponding placement delete would
be called).
What is a proper way to solve this kind of problem?

You don't care about it because it is not your concern: it is the
compiler implementers concern.
Let's not consider the possibility of bad_alloc. (If a bad_alloc
is thrown, there's no leak at least.)

Nor is there if the constructor of the object throws an exception.
 
E

ES Kim

Dietmar Kuehl said:
The people creating the C++ standard thought of this: if an exception
is thrown during step 2, all members constructed so far are destroyed
and then 'operator delete()' is called appropriately (i.e., if you
used a placement form of new, a corresponding placement delete would
be called).

That's reassuring, and I found the relevent phrase in the Standard.
Thank you.
 
S

Siemel Naran

struct S
{
S(int i) { if (i < 0) throw "oops"; }
};

int main()
try
{
auto_ptr<S> ap(new S(-1)); // A
}
catch (...)
{
}

Statement A can be considered step by step like this:
(1) raw memory is allocated by ::eek:perator new(sizeof(S))
(2) the memory is initialized by S::S(int)
(3) an auto_ptr is constructed pointing to the memory

Once step (2) throws, step (3) never happens, and the system calls steps
(1x)
(1x) raw memory is de-allocated by ::eek:perator delete(void*)

Please note that the system does NOT call (2x) because (2) did not run to
completion
(2x) the memory is de-initialized by S::~S()

However, if class S had member variables and the initialization list ran to
completion and it was the constructor body that threw an exception, then
rest assured that the system will call the destructors of the member
variables constructed till the exception was thrown. If S had a base class,
then I'm not sure if the destructor of the base class would get called, but
I imagine it would because it is kind of like a member variable.

Note that if there was a class S::eek:perator new, the system would call that
instead of the global operator new, and S::eek:perator delete.
But you see an exeption is thrown at step (2) and auto_ptr is
*not* constructed, which means ~auto_ptr is not called.
The net result is memory leak, of course.
What is a proper way to solve this kind of problem?
Let's not consider the possibility of bad_alloc. (If a bad_alloc
is thrown, there's no leak at least.)

Your code is fine.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top