Constructor creating this-handle must succeed!

There seems to be a major problem with handles pointing to "this" that are created in constructors that do not succeed.

I have two classes A and B. B needs to store an A handle (since A is a kind of parent). This handle is passed as an argument of the B constructor. Class A creates instances of B in its own constructor. But the constructor of A might fail, which results in throwing an exception.

This seems to be a standard situation to me. I have checked the web and throwing exceptions from constructors is considered "good programming", since a constructor has no return value and by throwing an exception it can signal, that something went wrong during construction.

But now there is a real problem. Please check the following pseudo code.

A::A()
{
// Create handle that can be passed during the creation of B.
Handle(A) thisHandle = this;

// Here let the constructor fail.
throw 0;

// Create B.
B instance(thisHandle);
}

When a constructor throws an exception, the construction was not finished and the destructor must not be called. But when thisHandle goes out of scope, it deletes this, which leads to a segmentation fault. If there was a way to prevent handles from deleting their stored pointer ("deactivate" the handle), I could catch the exception in the constructor of A, deactivate the handle and then rethrow the exception. But as far as I know there is no way to achieve that.

Has anyone experience with such problems? Have I made wrong design decisions?

To explain my design intentions: if creation of A succeeds, the caller of the A constructor would get the A handle and then both the construction context of A and B would store the same handle to A.

Thank you very much for any hint!

Forum supervisor's picture

Dear Benjamin,
It is definitely bad practice to create handle (or smart pointer of any kind) to "this" pointer inside class method, as you cannot know if this object is actually allocated in dynamic memory.
Doing this in constructor is yet worse, for the reason described.
The code must be refactored to avoid this. For instance, class B in the example could accept pointer (or reference) to class A instead of handle.
Note that OCCT handles (and smart pointers in general) are means to control lifetime of dynamically created objects.
Since class B is created by instance of class A which he points to, it may not know how A is created and be responsible for destruction of A, hence may not use smart pointer to refer to it.
At the same time if you have found such stuff in OCCT classes I suggest you to register the issue in Mantis BugTracker or at least point out these classes (files) explicitly.

Best regards
FSR
Best regards
FSR

Benjamin Bihler's picture

Thank you very much for your answer. It was very helpful.