Gibt es eine Möglichkeit, programmgesteuert festzustellen, ob ein bestimmter Speicherblock von FastMM nicht freigegeben wurde?

103

Ich versuche festzustellen, ob ein Speicherblock nicht freigegeben wurde. Natürlich sagt mir der Manager das per Dialogfeld oder Protokolldatei, aber was ist, wenn ich Ergebnisse in einer Datenbank speichern möchte? Zum Beispiel möchte ich in einer Datenbanktabelle Namen von Routinen haben, die bestimmte Blöcke zugewiesen haben.

Nachdem ich eine Dokumentation von FastMM gelesen habe, weiß ich, dass wir seit Version 4.98 die Möglichkeit haben, vom Manager über Speicherzuweisungen, Freigaben und Neuzuweisungen benachrichtigt zu werden, sobald diese auftreten. Zum Beispiel geht ein OnDebugFreeMemFinishEreignis an uns über, PFullDebugBlockHeaderdas nützliche Informationen enthält. Es PFullDebugBlockHeaderfehlt eine Sache - die Information, ob der angegebene Block von der Anwendung freigegeben wurde.

Es OnDebugFreeMemFinishsei denn, wird nur für nicht freigegebene Blöcke aufgerufen? Das weiß ich nicht und möchte es herausfinden.

Das Problem ist, dass OnDebugFreeMemFinishich selbst bei einem Ereignis nicht herausfinden konnte, ob der Block freigegeben wurde oder nicht.

Hier ist ein Beispiel:

program MemLeakTest;

{$APPTYPE CONSOLE}

uses
  FastMM4, ExceptionLog, SysUtils;


procedure MemFreeEvent(APHeaderFreedBlock: PFullDebugBlockHeader; AResult: Integer);
begin
//This is executed at the end, but how should I know that this block should be freed
//by application? Unless this is executed ONLY for not freed blocks.
end;

procedure Leak;
var
  MyObject: TObject;
begin
  MyObject := TObject.Create;
end;

begin
  OnDebugFreeMemFinish := MemFreeEvent;
  Leak;
end.

Was mir fehlt, ist der Rückruf wie:

procedure OnMemoryLeak(APointer: PFullDebugBlockHeader);

Nachdem ich die Quelle von FastMM durchsucht hatte, sah ich, dass es eine Prozedur gibt:

procedure LogMemoryLeakOrAllocatedBlock(APointer: PFullDebugBlockHeader; IsALeak: Boolean);

was könnte überschrieben werden, aber vielleicht gibt es einen einfacheren Weg?

Wodzu
quelle
7
Ich habe immer verstanden, dass FastMM diese Prüfung nur als die SEHR LETZTE Aktion durchführen kann, die das Programm per Definition ausführen sollte. Bis FastMM seinen Bericht erstellt, ist Ihr Code fertig. Um eine Teillösung zu erhalten, können Sie jederzeit in der Quelle nachsehen, wie der zugewiesene Speicher gekennzeichnet ist.
Brian Frost
6
Als erwartetes Leck gemeldet? Haben Sie es wie erwartet registriert? Sie können auch nicht entscheiden, dass Speicher bis zum Herunterfahren verloren geht, es sei denn, Sie stellen eine komplexe Logik bereit, die die erwarteten Lebensdauern versteht.
David Heffernan
6
Wenn OnDebugFreeMemFinishaufgerufen wird, bedeutet dies, dass der Block freigegeben wurde. Es gibt keine OnMemoryLeakVeranstaltung. Es könnte niemals ein solches Ereignis geben. FastMM stellt beim Herunterfahren fest, dass alle nicht freigegebenen Blöcke undicht sein müssen. Es kann kein Leck früher erkennen.
David Heffernan
12
Immer wenn FastMM mir mitteilt, dass ein Speicherverlust vorliegt, schalte ich die Tools aus und behebe ihn sofort. Wenn Sie das nicht tun, fällt es Ihnen schwer, das Leck zu reproduzieren. Wenn Sie sich wirklich in der Datenbank anmelden möchten, müssen Sie sich die CheckBlocksOnShutdown-Funktion ansehen. Ein weiterer möglicher Erweiterungspunkt ist AppendEventLog, dass Sie die von mir vermutete FastMM-Quelle ändern müssen.
David Heffernan
12
Ähm, nimm einfach die Datei, analysiere sie und lege sie in die Datenbank?
Tony Hopkinson

Antworten:

2

Selbst wenn ein solcher Handler vorhanden wäre, wäre er nahezu nutzlos, da alles, einschließlich der Datenbank, zu dem Zeitpunkt heruntergefahren würde, an dem FastMM Lecks meldet.

Also, ich schlage vor, dass Sie sich LogErrorsToFilezusammen mit den FullDebugModeBedingungen einschalten FastMM4Options.inc. Dadurch erhalten Sie eine Textdatei mit Lecks, die Sie später analysieren und in die Datenbank einfügen können.

Serhii Kheilyk
quelle