Exception in constructor calls destructor????

G

Guest

According to MSDN2, if a managed class throws an exception in the
constructor, the destructor will be called. If an exception is thrown in the
constructor the object never existed so how in the world can the destructor
of a object that does not exist get called!

Here is the MSDN2 document:

Code authored in Visual C++ and compiled with /clr will run a type's
destructor for the following reasons:
....
If an exception is thrown during the object's construction.
....

So for an exception is thrown in a "Parrot" class constructor:

"He's not pining! He's passed on! This Parrot is no more! He has ceased to
be! He's expired and gone to meet his maker! He's a stiff! Bereft of life, he
rests in peace! If you hadn't nailed him to the perch he'd be pushing up the
daisies! His metabolic processes are now history! He's off the twig! He's
kicked the bucket, he's shuffled off his mortal coil, run down the curtain
and joined the bleedin' choir invisible! This is an ex-Parrot!"

Which leads to:

Q: What does emitting an exception from a constructor mean?

A: It means that construction has failed, the object never existed, its
lifetime never began. Indeed, the only way to report the failure of
construction -- that is, the inability to correctly build a functioning
object of the given type -- is to throw an exception.

In biological terms, conception took place -- the constructor began --, but
despite best efforts it was followed by a miscarriage -- the constructor
never ran to term(ination).

Incidentally, this is why a destructor will never be called if the
constructor didn't succeed -- there's nothing to destroy. "It cannot die, for
it never lived." Note that this makes the phrase "an object whose constructor
threw an exception" really an oxymoron. Such a thing is even less than an
ex-object... it never lived, never was, never breathed its first. It is a
non-object.

So how do we rationalize calling the destructor in C++/cli when an exception
is thrown in the constructor?
 
V

Vladimir Nesterovsky

According to MSDN2, if a managed class throws an exception in the
constructor, the destructor will be called. If an exception is thrown in
the
constructor the object never existed so how in the world can the
destructor
of a object that does not exist get called!

In clr object starts its life when its memory is allocated and initialized
(by the runtime). In this sence constructor is just secondary initializer.
Which leads to:

Q: What does emitting an exception from a constructor mean?

A: It means that construction has failed, the object never existed, its
lifetime never began. Indeed, the only way to report the failure of
construction -- that is, the inability to correctly build a functioning
object of the given type -- is to throw an exception.

The fact that object did not finish its construction does not mean it never
existed.
 
G

Guest

Vladimir Nesterovsky said:
In clr object starts its life when its memory is allocated and initialized
(by the runtime). In this sence constructor is just secondary initializer.
existed.

This looks like Objective Cs id myInstance= [[MyClass alloc] init];
The fact that object did not finish its construction does not mean it never
existed.

You would have to argue with Herb Sutter about that one:

"An object's lifetime begins when its constructor completes.
Corollary: An object whose constructor did not complete never existed.
Corollary: The only way to report a failed construction is to exit the
constructor by means of an exception.
...."
 
C

Carl Daniel [VC++ MVP]

JAL said:
You would have to argue with Herb Sutter about that one:

"An object's lifetime begins when its constructor completes.
Corollary: An object whose constructor did not complete never existed.
Corollary: The only way to report a failed construction is to exit the
constructor by means of an exception.
..."

That's true for standard C++, but it's not true for the CLR. for better or
worse.

-cd
 
B

Bruno van Dooren

but that also means that in a destructor of a managed class you can't be
sure anymore that your object is initialized properly?

kind regards,
Bruno.
 
C

Carl Daniel [VC++ MVP]

Bruno said:
but that also means that in a destructor of a managed class you can't
be sure anymore that your object is initialized properly?

Yes and no.

For a managed class, the object is fully initialized by the CLR before the
ctor-initializer-list begins. All fields are initialized to their 'natural'
values - int are 0, references are null, bools are false, etc.

As Vladmir responded earlier, the ctor is really just a secondary
initializer.

-cd
 
H

Holger Grund

Yes and no.

For a managed class, the object is fully initialized by the CLR before the
ctor-initializer-list begins. All fields are initialized to their
'natural' values - int are 0, references are null, bools are false, etc.
This initialization includes the vtables, too. I.e. during the
explicitly coded construction (base & member ctors),
the object's dynamic type is always that of the most-derived
object. This in turn introduces problems with destroying
a partially constructed object. For instance, consider
the base class ctor succeeds but one of the member
ctors throws. There's no reliable way to invoke (only)
the destructor of the base class.

Additionally, it's probably well worth mentioning that MS's
point of view is that object destruction of managed objects
follows the Disposable pattern. That means your objects
should be prepared to handle multiple calls of the
destructor (because it's apparently not considered invalid
to call Dispose more than once on a given object).

I'd tend to say you simply have to forget the standard
C++ object lifetime & construction model.

At the risk of repeating myself, I don't think it's exactly
great design ...

-hg
 
B

Bruno van Dooren

Ok i get your meaning. i thought you meant that the destructor would be
called if an exception was thrown during the construction phase.

kind regards,
Bruno.
 
G

Guest

Carl.... I think that this type of non standard behaviour needs to be
explicitly pointed out to the unsuspecting coder who, IMHO, coming from C++
rightfully assumes that the destructor will not be called if an exception is
thrown in the user written constructor. I can easily think of examples where
this can cause trouble such as doing IncrementRefCount in the constructor and
DecrementRefCount in the destructor. It would then be possible to throw an
exception without a successful call to IncrementRefCount in the constructor
and then call DecrementRefCount on exception leaving the system in an invalid
state.
 

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

Top