[Delphi XE2] Contrôle des fuites mémoires avec FastMM4

Contrôle des fuites mémoires avec FastMM4 (Delphi XE2)

Introduction

Je précise que cet outil n'est pas de moi, mais de Pierre le Riche. Il me semblait intéressant de publier cet article car sur internet, je n'ai trouvé d'aide qu'en anglais, et par ailleurs, ça peut permettre de localiser très rapidement des fuites dans les programmes.

Installation

Voici les étapes de la procédure d'installation:

  • Télécharger le zip à l'adresse suivante : http://sourceforge.net/projects/fastmm/
  • Pour une utilisation systématique, le dézipper, et placer les unités FastMM4.pas, FastMM4Messages.pas et FastMM4Options.inc dans un dossier dont le chemin est ajouté dans la liste des bibliothèques de Delphi (menu Outils > Options > Bibliothèque > Chemin de bibliothèque),
  • Dans le fichier source du projet (fichier .dpr), ajouter FastMM4 en première position dans le paragraphe Uses,
  • Sur le FormCreate par exemple de la fiche principale, ajouter l'indicateur de détection de fuite mémoire (ReportMemoryLeaksOnShutDown := True)
  • Dans le fichier FastMM4Options.inc, il y a énormément d'options. Je ne peux pas toutes les décrire ici, c'est à vous de choisir lesquelles activer pour votre utilisation.

Quelques petites options qui peuvent être intéressantes cependant :
FullDebugMode + LogErrorsToFile + LogMemoryLeakDetailToFile : Permet d'enregistrer les erreurs dans un fichier texte que l'on retrouve dans le dossier de l'exécutable (très pratique pour l'analyse d'une application service Windows). L'activation du FullDebugMode nécessite la DLL FastMM_FullDebugMode.dll dans le dossier de l'exécutable (A voir : Pour une utilisation systématique, la DLL peut être installée dans le dossier système de windows...).
Toutes les options sont décrites (en anglais).

Exemple d'utilisation

Fichier dpr

program TestFastMM;

uses
{$IFDEF DEBUG}
  fastMM4,
{$ENDIF}
  Vcl.Forms,
  UMain in 'UMain.pas' {FMain};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TFMain, FMain);
  Application.Run;
end.

Fichier pas

unit UMain;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TFMain = class(TForm)
    btn_Create: TButton;
    procedure FormCreate(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
  end;

var
  FMain: TFMain;

implementation

{$R *.dfm}

procedure TFMain.FormCreate(Sender: TObject);
var
   slTest : TStrings;
begin
     // Rapport de fuite mémoire sur la configuration de débuggage
     ReportMemoryLeaksOnShutdown := (DebugHook <> 0);
     // Création d'une Stringlist, sans la libérer pour générer une
     // fuite mémoire à la fermeture de l'application
     slTest := TStringList.Create;
end;

end

Rapport d'exécution FastMM

Suite à l'exécution du programme, et en ayant activé les options suggérées plus haut, on trouve un fichier, avec le nom [nom du projet]_MemoryManager_EventLog.txt, qui dans le cas du programme de cet exemple contient :

--------------------------------2013/10/3 16:44:18--------------------------------
A memory block has been leaked. The size is: 100

This block was allocated by thread 0x13B4, and the stack trace (return addresses) at the time was:
4046FA [System][@GetMem$qqri]
405137 [System][TObject.NewInstance$qqrv]
4057A6 [System][@ClassCreate$qqrpvzc]
44D006 [System.Classes][Classes.TStringList.$bctr$qqrv]
42A0DD [System.SysUtils][Sysutils.TThreadLocalCounter.HashIndex$qqrv]

515D74 [UMain.pas][UMain][TFMain.FormCreate$qqrp14System.TObject][34]
42A12A [System.SysUtils][Sysutils.TThreadLocalCounter.Open$qqrrp27System.Sysutils.TThreadInfo]
50352F [Vcl.Forms][Forms.TCustomForm.DoCreate$qqrv]
503173 [Vcl.Forms][Forms.TCustomForm.AfterConstruction$qqrv]
405814 [System][@AfterConstruction$qqrp14System.TObject]
503142 [Vcl.Forms][Forms.TCustomForm.$bctr$qqrp25System.Classes.TComponent]

The block is currently used for an object of class: TStringList

The allocation number is: 635

Current memory dump of 256 bytes starting at pointer address 7EF6FD40:
70 EB 43 00 00 00 00 00 00 00 00 00 F0 C2 F9 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 8D BA 7D
80 80 80 80 80 80 80 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
p ë C . . . . . . . . . ð Â ù ~ . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . à º }
€ € € € € € € € . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

--------------------------------2013/10/3 16:44:18--------------------------------
This application has leaked memory. The small block leaks are (excluding expected leaks registered by pointer):

85 - 100 bytes: TStringList x 1

Note: Memory leak detail is logged to a text file in the same folder as this application. To disable this memory leak check, undefine "EnableMemoryLeakReporting".

La ligne en gras dans ce rapport indique clairement qu'il y a une fuite sur la ligne 34 de l'unité UMain. Effectivement, une stringlist est créée sans être libérée.

Conclusion

Cet outil permet donc de contrôler l'imperméabilité du programme (je ne sais pas vraiment si ça se dit, mais c'est bien de ça qu'il s'agit), et d'indiquer assez précisément l'origine des fuites mémoire.

A voir également
Ce document intitulé « [Delphi XE2] Contrôle des fuites mémoires avec FastMM4 » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Rejoignez-nous