pickzy.com

C  |  C++  |  Objective-C  |  VC++  |  Win32  |  MFC  |  Java  |  Php  |  Delphi  |  Visual Basic  |  .Net  |  Networking  |  General  |  Games  |  Jobs  |  Javascript  |  




Menu

pickSourcecode.com


        

 




 

Delphi > Articles

 

Delphi - How to avoid Memory Leaks?

 
 

 How to avoid Memory leaks?

 
     
  Why Delphi cannot free your memory for you
  Delphi implements objects by reference. When you declare an object :
 
 
 
 var
   rover : TCar;
  you are simply declaring a reference to an object. When you create an object for this reference :
 
 
 
 begin
   rover := TCar.Create;
  Delphi allocates memory for the object, and executes the Create constructor method of the class to do any object initialisation required. The rover variable now points to this new object. There is no magic link from the object to the variable - simply a reference.
 
 
  You can make a second reference to the object :
 
 
 
 var
   rover : Tcar;
   myCar : TCar;
 
 begin
   rover := TCar.Create;
   myCar := rover;
  The myCar assignment simply makes the myCar variable point to the object that rover points to. No copying of the object is done. Only one object exists at this time. And it is not magically linked to either variable.
 
 
  Delphi does not keep track of who has referred to the object because it cannot easily keep track of all possible variables that might refer to the object. So, for example, you could set both of these variables to nil and the object will still persist.
 
 
  How the memory leaks normally occur
  In many parts of many programs, you will have a function or procedure that creates one or more objects in order to carry out it's operation. Here is an example :
 
 
 
 procedure PrintFile(const fileName : string);
 var
   myFile   : TextFile;
   fileData : TStringList;
   i        : Integer;
 
 begin
   // Create the TSTringList object
   fileData := TStringList.Create;      // This allocates object memory
 
   // Load the file contents into the string list
   fileData.LoadFromFile(fileName);     // Expands the object memory size
 
   // Open a printer file
   AssignPrn(myFile);
 
   // Now prepare to write to the printer
   ReWrite(myFile);
 
   // Write the lines of the file to the printer
   for i := 0 to fileData.Count-1 do
     WriteLn(myFile, fileData[i]);
 
   // Close the print file
   CloseFile(myFile);
 end;
  Each time this procedure is called, a new TStringList object is created and filled with the contents of a file. You might think that Delphi would discard the old object when you are assigning the new object to fileData. But this does not happen because Delphi does not know if this is the only variable referring to the object.
 
 
  So you must add the following code to the end of the procedure to free up the memory:
 
 
 
   // Free up the string list memory
   FreeAndNil(fileData);
  This allows the procedure to be called as many times as you want without more memory being allocated for the string list object each time. We have avoided a memory leak.
 
 
  Memory used within an object
  Classes frequently allocate objects in the constructor and in methods. The allocations in the methods should be freed in line, as described above.
 
 
  But the objects allocated in the constructor should be freed in a Destructor method. It is like a converse process. But do not code these Free (or FreeAndNil) statements glibly. Take care to see how the class carries out allocations. It may, for example, create objects for a caller for these to persist after the current object is destroyed.
 
 
  Here is an example of a class with appropriate memory handling :
 
 
 
 unit MyClass;
 
 interface
 
 uses
   Classes;
 
 type
   TMyClass = class
   private
     fileData : TStringList;
   published
     Constructor Create(const fileName : string);
     Destructor  Destroy; override;
     procedure   PrintFile;
   end;
 
 implementation
 
 uses
   Printers, Dialogs, SysUtils;
 
 // Constructor - builds the class object
 constructor TMyClass.Create(const fileName: string);
 begin
   // Create the string list object used to hold the file contents
   fileData := TStringList.Create;
 
   // And load the file data into it
   try
     fileData.LoadFromFile(fileName);
   except
     ShowMessage('Error : '+fileName+' file not found.');
   end;
 end;
 
 // Destructor - frees up memory used by the class object
 destructor TMyClass.Destroy;
 begin
   // Free up the memory used by the string list object
   FreeAndNil(fileData);
 
   // Call the parent class destructor
   inherited;
 end;
 
 // Print the file passed to the constructor
 procedure TMyClass.PrintFile;
 var
   myFile   : TextFile;
   i        : Integer;
 
 begin
   // Open a printer file
   AssignPrn(myFile);
 
   // Now prepare to write to the printer
   ReWrite(myFile);
 
   // Write the lines of the file to the printer
   for i := 0 to fileData.Count-1 do
     WriteLn(myFile, fileData[i]);
 
   // Close the print file
   CloseFile(myFile);
 end;
 
 end.
  Note that in this example, the object holds the file, and the caller calls the PrintFile method without respecifying the file name. When an object of this class is destroyed, the string list containing the file contents is also destroyed.
 
 
  On Windows XP, the Task Manager shows the memory allocated to running processes. It is useful to observe the allocation amount for your application as you use it. There is likely to be some upping of memory useage as you use different functions, but repeated calls to the same function should normally yield a stable memory allocation.
 

 
Privacy Policy | About Us