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

Michael Van Canneyt michael at freepascal.org
Thu Jul 2 17:09:24 CEST 2009



On Thu, 2 Jul 2009, Martin Friebe wrote:

> 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

Yes, because there is no way to know what happens in the
constructor/destuctor in a descendent/parent class...

>
>
> 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)?

Not that I am aware of. But someone familiar with the compiler internals
should confirm this.

Michael.

Michael.

>
>
> Thanks for the explanation so far
> Martin
> _______________________________________________
> fpc-pascal maillist  -  fpc-pascal at lists.freepascal.org
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>



More information about the fpc-pascal mailing list