Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2014-08

why dynamic array created in constructor not automatically free in destructor

5 messages · 4 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Dennis Poon
I have a class like;
------------
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?

Dennis

Jürgen Hestermann
to Dennis Poon
Dennis Poon wrote 18 lines
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.

Michael Van Canneyt
to Jürgen Hestermann
Jürgen Hestermann wrote 38 lines
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.

Jürgen Hestermann
to Michael Van Canneyt
Michael Van Canneyt wrote
The compiler frees dynamic arrays.

Does this happen too if you declare a dynamic array locally in a function and leave this function?

leledumbo
to Jürgen Hestermann
Does this happen too if you declare a dynamic array locally in a function

and leave this function?

The global rule: as soon as the reference count reaches 0, the array gets unallocated, wherever it's declared and as long as it's accessed normally without any hack.