Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Memory leak using TList?


This question is answered.


Permlink Replies: 6 - Last Post: Mar 30, 2016 5:47 AM Last Post By: David Cox
David Cox

Posts: 28
Registered: 7/6/07
Memory leak using TList?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 29, 2016 8:48 AM
Hello All,

I use an exception handler MadException that also reports on memory leaks (BTW, a great tool!). It is indicating I have a memory leak in the following program (example modified from the Delphi Basics site to illustrate the error). The memory leak reported occurs during the TCustomer.Create. I am using Delphi 10 Seattle.

Any ideas on what I am doing wrong?

Thanks!

unit Unit2;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 
type
  // The customer class definition
  TCustomer = class
    private
      // The data fields of this new class
      CustomerName   : String;
      CustomerNumber : Integer;
    public
      constructor Create(const CustomerName   : String;
                         const CustomerNumber : Integer);
  end;
 
  TForm2 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
 
  private
    myList : TList;
   end;
 var
  Form2: TForm2;
 
implementation
 
{$R *.dfm}
 
// Customer constructor
// --------------------------------------------------------------------------
constructor TCustomer.Create(const CustomerName   : String;
                             const CustomerNumber : Integer);
begin
  self.CustomerName   := CustomerName;
  self.CustomerNumber := CustomerNumber;
end;
 
 
// --------------------------------------------------------------------------
procedure TForm2.FormCreate(Sender: TObject);
var
  customer : TCustomer;
 
begin
  myList := TList.Create;
  myList.Add(TCustomer.Create('Bill Gates', 123));   //Memory leak caused here;
  myList.Add(TCustomer.Create('Steven Jobs', 456));  //Memory leak caused here
  FreeAndNil(myList);
end;
 
// --------------------------------------------------------------------------
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action:=caFree;
end;
 
end.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Memory leak using TList?
Correct
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 29, 2016 9:02 AM   in response to: David Cox in response to: David Cox
David wrote:

I use an exception handler MadException that also reports on memory
leaks (BTW, a great tool!). It is indicating I have a memory leak in
the following program (example modified from the Delphi Basics site to
illustrate the error). The memory leak reported occurs during the
TCustomer.Create.

TList is just a list of memory pointers. You are responsible for managing
the lifetimes of any objects you add to the list. Since you are not freeing
the object in your code, they are leaked. You need to free them manually,
eg:

myList := TList.Create;
...
myList.Add(TCustomer.Create('Bill Gates', 123)); //Memory leak caused here;
myList.Add(TCustomer.Create('Steven Jobs', 456)); //Memory leak caused here
...
// add this!
for I := 0 to myList.Count-1 do begin
  TCustomer(myList[I]).Free;
end;
...
FreeAndNil(myList);


If you want the list to take ownership of the objects and free them automatically
for you, use a TObjectList instead, and set its OwnsObjects property to True
(which it is by default).

--
Remy Lebeau (TeamB)
John Kouraklis

Posts: 209
Registered: 3/10/01
Re: Memory leak using TList?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 29, 2016 9:15 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
David wrote:

I use an exception handler MadException that also reports on memory
leaks (BTW, a great tool!). It is indicating I have a memory leak in
the following program (example modified from the Delphi Basics site to
illustrate the error). The memory leak reported occurs during the
TCustomer.Create.

TList is just a list of memory pointers. You are responsible for managing
the lifetimes of any objects you add to the list. Since you are not freeing
the object in your code, they are leaked. You need to free them manually,
eg:

myList := TList.Create;
...
myList.Add(TCustomer.Create('Bill Gates', 123)); //Memory leak caused here;
myList.Add(TCustomer.Create('Steven Jobs', 456)); //Memory leak caused here
...
// add this!
for I := 0 to myList.Count-1 do begin
  TCustomer(myList[I]).Free;
end;
...
FreeAndNil(myList);


If you want the list to take ownership of the objects and free them automatically
for you, use a TObjectList instead, and set its OwnsObjects property to True
(which it is by default).

--
Remy Lebeau (TeamB)

Remy, out of interest, why did you use FreeAndNil?

I know what it does but isn't it enough to just free myList?

I know there is lot of discussion about nil-ling objects is not good idea.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Memory leak using TList?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 29, 2016 10:04 AM   in response to: John Kouraklis in response to: John Kouraklis
John wrote:

Remy, out of interest, why did you use FreeAndNil?

Because David's original code is using it. I did not change that. The variable
is a member of the Form, but is being created and freed within the same procedure.
If there were other code in the Form that checks the variable for nil, it
would make sense to nil it after freeing it. The point of this discussion
is to explain how to free the objects stored inside the list, not how to
free the list itself.

--
Remy Lebeau (TeamB)
Rudy Velthuis (...


Posts: 7,731
Registered: 9/22/99
Re: Memory leak using TList?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 29, 2016 10:22 AM   in response to: John Kouraklis in response to: John Kouraklis
John Kour wrote:

Remy, out of interest, why did you use FreeAndNil?

I know what it does but isn't it enough to just free myList?

Yes, it is, especially if that code is found in a destructor.

--
Rudy Velthuis http://www.rvelthuis.de

"There are very few monsters who warrant the fear we have of
them."
-- Andre Gide
David Cox

Posts: 28
Registered: 7/6/07
Re: Memory leak using TList?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 30, 2016 5:47 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Thank you Remy! That resolved the problem.

Dave
John Kouraklis

Posts: 209
Registered: 3/10/01
Re: Memory leak using TList?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Mar 29, 2016 9:13 AM   in response to: David Cox in response to: David Cox
David Cox wrote:
Hello All,

I use an exception handler MadException that also reports on memory leaks (BTW, a great tool!). It is indicating I have a memory leak in the following program (example modified from the Delphi Basics site to illustrate the error). The memory leak reported occurs during the TCustomer.Create. I am using Delphi 10 Seattle.

Any ideas on what I am doing wrong?

Thanks!

unit Unit2;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 
type
  // The customer class definition
  TCustomer = class
    private
      // The data fields of this new class
      CustomerName   : String;
      CustomerNumber : Integer;
    public
      constructor Create(const CustomerName   : String;
                         const CustomerNumber : Integer);
  end;
 
  TForm2 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
 
  private
    myList : TList;
   end;
 var
  Form2: TForm2;
 
implementation
 
{$R *.dfm}
 
// Customer constructor
// --------------------------------------------------------------------------
constructor TCustomer.Create(const CustomerName   : String;
                             const CustomerNumber : Integer);
begin
  self.CustomerName   := CustomerName;
  self.CustomerNumber := CustomerNumber;
end;
 
 
// --------------------------------------------------------------------------
procedure TForm2.FormCreate(Sender: TObject);
var
  customer : TCustomer;
 
begin
  myList := TList.Create;
  myList.Add(TCustomer.Create('Bill Gates', 123));   //Memory leak caused here;
  myList.Add(TCustomer.Create('Steven Jobs', 456));  //Memory leak caused here
  FreeAndNil(myList);
end;
 
// --------------------------------------------------------------------------
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action:=caFree;
end;
 
end.

If you use TObjectList<TCustomer> you don't have to worry about freeing the classes manually.
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02