Delphi raise exception in constructor

Your code is absolutely fine and correct. Raising exceptions from constructors is perfectly respectable. As you know the destructor is called.

You ask about this code:

a := TCombinatorio.Create(5,-2);
try
  //some code
finally
  a.Free; 
end;

You are worried that Free will be called after the object has already been destroyed. That cannot happen. If an exception is raised in the constructor then it propagates up the call stack. That happens before the try block begins and so the finally block does not execute. Indeed the assignment to a does not happen.

Moving the creation inside the try would be disastrous and is in fact an incredibly common mistake. Suppose you did that:

// WARNING THIS CODE IS DEFECTIVE 
try
  a := TCombinatorio.Create(5,-2);
  //some code
finally
  a.Free; 
end;

Now if an exception is raised then Free is called but on what? The variable a is not initialized. Even if it was, which it isn't, that would still be a double free.


OK, first you can raise an exception in the constructor, and yes it does call the destructor as a consequence. The code you show is fine. But I think you misunderstand what your code does. And to put the constructor inside a try finally block would be wrong. The point I think that you are missing is that if your constructor fails the try...finally block never gets executed and so the free is not executed. You should not call free if the constructor does not succeed, which is why you should not put the constructor inside the try...finally block.


First of all I would say that you cannot avoid exceptions in constructors so it cannot be an anti-pattern. If you check Delphi source code you will find number of places where exception is raised in constructor. For example

constructor TCustomForm.Create(AOwner: TComponent);
begin
  // ... skipped some lines
        if not InitInheritedComponent(Self, TForm) then
          raise EResNotFound.CreateFmt(SResNotFound, [ClassName]);

The only thing you should know is that Delphi will automatically call the destructor if an exception escapes from the constructor. Actually it means that your destructor may be executed on a partially constructed object and it is your responsibility to write destructor properly. See TObject.Destroy documentation, and pay your special attention to the below quote:

Note: If an exception escapes from the constructor, the destructor is called to destroy the partially constructed object instance that failed to initialize completely. Therefore, destructors should check that allocated resources such as handles were actually allocated before trying to release them, since their value might be zero.

PS In general you should assume that each line of code may raise an exception, but please do not be a paranoiac ;)

Tags:

Delphi