[Date Prev][Date Next][Thread Prev][Thread Next][Author Index][Date Index][Thread Index]

Obscure behavior of CONSTRUCTOR_BOMB() when a member object fails construction.



The CONSTRUCTOR_BOMB() mechanism (as implemented for cfront 2.0)
has an undesirable behavior, as follows:

When a class contains members which are themselves classes with constructors,
and one of these member class constructors fails (i.e., does a BLAST() which
it does not catch itself), the class will be destroyed as if the construction
had been successful, i.e.:

 - The class' destructor will be called, EVEN THOUGH THE BODY OF ITS
   CONSTRUCTOR WAS NOT EXECUTED, then

 - The destructors of ALL the member classes, EVEN THOSE WHOSE CONSTRUCTORS
   WERE NEVER CALLED, will be called.

If the class containing the member class that failed is a member of a
hierarchy of derived classes, the resulting instance will be destroyed
as if construction had been completed through the level of the class
hierarchy containing the member class whose constructor failed.

Thus, if:

	- B is a base class
	- C is a class derived from B, containing the member classes:
	     - Foo
	     - Bar
	     - Baz
	- D is a class derived from C

the normal execution of constructor code would be:

	B()
	Foo()
	Bar()
	Baz()
	C()   (actually, the body of the C() constructor)
	D()

and the normal execution of destructor code would be:

	~D()
	~C()
	~Baz()
	~Bar()
	~Foo()
	~B()

But if the constructor Bar() fails, the execution order would be:

	B()
	Foo()
	Bar()
	~C()	// wrong
	~Baz()	// wrong
	~Bar()
	~Foo()
	~B()

Unfortunately, cfront 2.0 does not provide sufficient hooks for
writing a workaround that would produce the correct behavior
(suppressing ~C() and ~Baz()).

Several workarounds are possible, however:

 - Instead of member classes, use member pointers to heap
   allocated instances (which are allocated in the constructor
   of the containing classes, and deleted in the corresponding
   destructor).

 - Avoid member classes with constructors.

 - Avoid member classes whose constructors can fail.

 - (Heap-allocated instances only):  Use a memory allocator which clears
   the instance's storage, and test a construction-state member variable
   in all vulnerable destructors.

	michael