implicit exception frames? [Re: [fpc-pascal] If an Assert fails in constructor, then destructor called (?)]

Martin Friebe fpc at mfriebe.de
Thu Jul 2 16:58:38 CEST 2009


Michael Van Canneyt wrote:
> On Thu, 2 Jul 2009, Martin Friebe wrote:
>> Inoussa OUEDRAOGO wrote:
>>> Indeed, when an exception is raised in the constructor, be it an
>>> "assert" exception or not, the destructor is called to allow the
>>> developer to clean up the "in-construction" instance's members he has
>>> already initialized.
>>>
>> I just cam across this thread. While I am not opposing the behaviour 
>> as it's stand (it could be useful anyway), it raises another question.
>>
>> Does that mean that an implicit exception-frame (or whatever this is 
>> called) is inserted *each* time you create/instantiate an object?
>>
>> Now I understand, object instantiation comes at a cost anyway (memory 
>> allocation), this does add to the cost of instantiation. And the only 
>> error/exception, which really *all* classes can encounter in a 
>> constructor, is out of memory for the object itself => In which case 
>> create is never called (because NewInstance fails), and Destroy 
>> should not be called (as there is no instance that could be passed to 
>> destroy).
>> So There could be calls to create where a developer does not want 
>> (and not need) any exception stack frame.
>>
>> I also wonder why this special kind of "garbage collector"? Pascal 
>> has automatic behaviour to handle/free resources for:
>> - strings
>> - open array
>> - apparently classes/objects, but only inside the constructor ?
>>
>> The last one does of course not apply to objects hold by the failed 
>> object, but I assume that, if Destroy is called, the instance is also 
>> freed?
>> So why are objects handled special in the constructor? If they raise 
>> an exception anywhere else in there live, then you need to care 
>> yourself about catching it, and freeing them?
>
> Because you cannot handle it yourself. Assume the following statement:
>
>   MyClass:=TSomeClass.Create;
>
> if an exception happens inside the constructor, then no instance 
> pointer is assigned to MyClass, since execution after the exception is 
> raised is continued at the next except/finally block.
> That means you cannot handle destruction in the except block (assuming 
> you
> wrote one) since you have no pointer to work with.
>
> Therefor the constructor code must call the destructor in case of an 
> error.
Yes, of course, you are right. It is impossible to handle it in the 
calling code. As the order is:
- instantiation (NewInstance)
- Create
  - exception
- assignment to local var => never executed

But you can handle it yourself inside the constructor.
No one stops the developper from wrtiting

Constructor TFoo.Create;
begin
  try
   ...
  except
    self.Destroy; // Or Free ?
  end;
end;


- If an error/exception (out of mem) happens in NewInstance, neither 
Create nor Destroy are called (and neither can they be called, because 
they need an (empty) instance and there is none)
- If an error in Create happens, self is assigned (inside Create). So it 
can be acted on.
Even if, in the above example, this Create was called by a child-class 
via inherited Create. There is no worry (not even if self.Free is used), 
that the inherited constructor will find an invalid pointer in self 
(because/if it has been freed). The code above, never returns to the 
inherited constructor, unless this inherited constructor itself catches 
the exception too (in which case it must check ; It would need to be 
flagged on the exception object)

Anyway, while possible, it would be far to complicated. So I agree, the 
automated handling, ensuring the instance is Destroyed and freed once 
only, is probably the best


Leaves question 2: Is there a way to switch it off, to avoid the cost of 
creating an exception frame? (if you are either sure your constructor 
does not throw an exception, or for some reason do not care)?


Thanks for the explanation so far
Martin



More information about the fpc-pascal mailing list