[fpc-pascal] why dynamic array created in constructor not automatically free in destructor

Michael Van Canneyt michael at freepascal.org
Thu Aug 7 11:32:18 CEST 2014



On Thu, 7 Aug 2014, J├╝rgen Hestermann wrote:

> Am 2014-08-07 10:21, schrieb Dennis Poon:
>> TMyClass=class
>> public
>>   ar : array of integer;
>>   constructor Create;
>>  destructor destroy;override;
>> end;
>> TMyClass.Create;
>> begin
>>    inherited;
>>    SetLength(ar, 100);
>> end;
>> TMyClass.Destroy;
>> begin
>>    ar := nil;//<--- this is needed otherwise a memory leak is reported!
>>   inherited;
>> end;
>> I would expect the compiler would automatically insert this ar := nil on my 
> behalf because it seems like it does it for strings.
>> Am I missing some compiler directives?
>
>
> I think strings are a very special case because they are treated diffently in 
> many cases.
> Strings can be freed without harm because they are well defined and no parts 
> of them
> point to other objects on the heap. They have a reference counter where the 
> compiler
> logs how many instances are pointing to the string and only removes it when 
> it has
> reached zero.
>
> If you have a dynamic array then elements may point to other structures 
> (which again
> may point to a structure that....) which again need to be freed.
> If you have allocated memory yourself then the compiler does not know
> how (and when) to free these objects. They may be used in other arrays or 
> elsewhere.

The compiler frees dynamic arrays.

The following program:

Type
  TMyClass=class
  public
    ar : array of integer;
    constructor Create;
   destructor destroy;override;
  end;
  Constructor TMyClass.Create;
  begin
     inherited;
     SetLength(ar, 100);
  end;
Destructor TMyClass.Destroy;
  begin
//    ar := nil;//<--- this is needed otherwise a memory leak is reported!
    inherited;
  end;


begin
   With TMyClass.Create do
     Free;
end.

Reports 2 allocated blocks, and 2 free blocks. Exactly as you would expect:
home: >fpc -S2 -gh ta.pp
/usr/bin/ld: warning: link.res contains output sections; did you forget -T?
home: >./ta
Heap dump by heaptrc unit
2 memory blocks allocated : 432/432
2 memory blocks freed     : 432/432
0 unfreed memory blocks : 0
True heap size : 294912
True free heap : 294912


What can happen is that you did somewhere a
   B:=MyClass.ar;

and as long as B is in scope, the reference count of A is not 0 when the object is freed, and the array is also not freed.
(the ar:=nil will not change that)

Another possibility is a forgotten 'inherited' somewhere in a destructor.

Michael.


More information about the fpc-pascal mailing list