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.
Voici les étapes de la procédure d'installation:
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).
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.
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
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.
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.