[für mich hier gelöst] Großer Heap dump unfreed memory: wie vorgehen?

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Antworten
Ich934
Lazarusforum e. V.
Beiträge: 370
Registriert: So 5. Mai 2019, 16:52
OS, Lazarus, FPC: ArchLinux und Windows mit FPCUPdeluxe (L: 3.6, FPC 3.2.2)
CPU-Target: x86_64, i386
Wohnort: Bayreuth

[für mich hier gelöst] Großer Heap dump unfreed memory: wie vorgehen?

Beitrag von Ich934 »

Hallo,

ich habe hier ein Projekt, das bei bestimmten Schritten reproduzierbar im Debug einen Heap Dump mit unfreed memory erzeugt. An sich schon mal sehr gut, denn ich kann das reproduzieren.

Problem ist jedoch, dass ich aus diesen fast 3.500 Zeilen nicht schlau werde. Im Prinzip steht dort immer wieder das gleiche drinnen und die genannten Zeilen in meinem Programm werden sauber mit freigegeben. Vermutlich habe ich hier etwas übersehen. Ich bin das schon zeilenweise im Debug durchgegangen, aber mir ist auch nichts aufgefallen.

Bei anderen Heap dumps konnte ich ja die fehlerhafte Stelle problemlos identifizieren und das Problem beheben.

Hat hier jemand einen Tipp/Idee, wie man in solchen Fällen noch vorgehen kann? Ich bin ja sicher nicht der Einzige, der ein solches Problem hat.

Schöne Grüße
Zuletzt geändert von Ich934 am Do 5. Sep 2024, 06:13, insgesamt 1-mal geändert.
Tipp für PostgreSQL: www.pg-forum.de

Benutzeravatar
Zvoni
Beiträge: 396
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: Großer Heap dump unfreed memory: wie vorgehen?

Beitrag von Zvoni »

Für jedes "New" brauchst du ein "Dispose"
Für jedes "GetMem" ein "FreeMem"
Für jedes "Create" ein "Free"
.... und was mir sonst gerade nicht einfällt

Hast du HeapTrc an?
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Ich934
Lazarusforum e. V.
Beiträge: 370
Registriert: So 5. Mai 2019, 16:52
OS, Lazarus, FPC: ArchLinux und Windows mit FPCUPdeluxe (L: 3.6, FPC 3.2.2)
CPU-Target: x86_64, i386
Wohnort: Bayreuth

Re: Großer Heap dump unfreed memory: wie vorgehen?

Beitrag von Ich934 »

Hallo,

ja, das ist an sich bekannt und irgendwo wird das vergessen sein bzw. es wird eine Kombination auftreten, wo etwas nicht freigegeben wird. Die Frage ist, ob es eine Möglichkeit gibt, diesen riesigen Dump, der nicht viel aussagt, diese Information zu entlocken. Ansonsten war das ja immer kein Problem, wenn doch mal Speicher nicht freigegeben wurde.

Ja, ist natürlich aktiv, sonst würde ich den Dump ja nicht bekommen.
Tipp für PostgreSQL: www.pg-forum.de

Benutzeravatar
Zvoni
Beiträge: 396
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: Großer Heap dump unfreed memory: wie vorgehen?

Beitrag von Zvoni »

Hast du vielleicht nen "Klassiker" im Einsatz?
Ich denke da an FindAllFiles
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Ich934
Lazarusforum e. V.
Beiträge: 370
Registriert: So 5. Mai 2019, 16:52
OS, Lazarus, FPC: ArchLinux und Windows mit FPCUPdeluxe (L: 3.6, FPC 3.2.2)
CPU-Target: x86_64, i386
Wohnort: Bayreuth

Re: Großer Heap dump unfreed memory: wie vorgehen?

Beitrag von Ich934 »

Nein. Ich habs gerade eben gefunden. In einer verdammt blöden Stelle wurde eine Klasse neu erzeugt und in einer bestimmten Kombination nicht freigegeben. Das ist beim Durchgehen nicht aufgefallen und bei 3.500 Zeilen Dump, der im Prinzip immer das Gleiche anzeigt, nicht aufgefallen. Vor allem, weil er genau das nicht zeigt...

Aber eine Lösung, wie man bei solchen riesigen Dumps vorgeht, hat sonst keiner?
Tipp für PostgreSQL: www.pg-forum.de

Benutzeravatar
Zvoni
Beiträge: 396
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz 2.2.2 FPC 3.2.2)
CPU-Target: 32Bit
Wohnort: BW

Re: Großer Heap dump unfreed memory: wie vorgehen?

Beitrag von Zvoni »

Ich geh mal von aus dass du GlobalSkipIfNoLeaks aktiviert hast?
Und den HeapTrc auf ne Datei umleitest? SetHeapTraceOutput('Trace.log');

https://wiki.freepascal.org/heaptrc

oder vielleicht LeakView?
https://wiki.freepascal.org/leakview
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Ich934
Lazarusforum e. V.
Beiträge: 370
Registriert: So 5. Mai 2019, 16:52
OS, Lazarus, FPC: ArchLinux und Windows mit FPCUPdeluxe (L: 3.6, FPC 3.2.2)
CPU-Target: x86_64, i386
Wohnort: Bayreuth

Re: Großer Heap dump unfreed memory: wie vorgehen?

Beitrag von Ich934 »

Ja schon. Sonst macht das ja keinen Sinn bei solchen Ausgaben hier zu suchen ;-)
Tipp für PostgreSQL: www.pg-forum.de

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6848
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Großer Heap dump unfreed memory: wie vorgehen?

Beitrag von af0815 »

Es macht bei einem riesigen Dump auch keinen Sinn sich blöd zu suchen. Man nimmt die ersten 10 Vorfälle, schaut sich die an und hat meisten 90% erledigt.
Und ja die Stellen sind immer blöd gelaufen. Weil sonst hätte man die auch nicht im Dump.

Generell, je früher man anfängt umso weniger Probleme hat man. Bei mir ist das erste, das ganze zu aktivieren, dann erst zu programmieren, so mit fällt einem das sofort auf und nicht später auf den Kopf.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Ich934
Lazarusforum e. V.
Beiträge: 370
Registriert: So 5. Mai 2019, 16:52
OS, Lazarus, FPC: ArchLinux und Windows mit FPCUPdeluxe (L: 3.6, FPC 3.2.2)
CPU-Target: x86_64, i386
Wohnort: Bayreuth

Re: Großer Heap dump unfreed memory: wie vorgehen?

Beitrag von Ich934 »

Guten Morgen,

ja, das ist einer der ersten Sachen, die ich aktiviere und einbaue. Hier ist es halt dumm gelaufen, da dieser Fehler halt nur in einer bestimmten Konstellation aufgetreten ist - so wie es sich für einen echten Bug gehört, der dann in sich schön versachtelt ist, mit Menüaufrufen etc.

In meinem Fall, und ich habe mir jetzt den Dump noch mal angeschaut, da ich ja jetzt genau weiß, wonach ich suchen muss, wäre ich so nach Zeile 700 drauf gekommen. Aber auch nur so indirekt. Egal. Fehler gefunden und hoffen, dass so was doofes einfach nicht mehr vorkommt.
Tipp für PostgreSQL: www.pg-forum.de

Mathias
Beiträge: 6956
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: [für mich hier gelöst] Großer Heap dump unfreed memory: wie vorgehen?

Beitrag von Mathias »

Aber eine Lösung, wie man bei solchen riesigen Dumps vorgeht, hat sonst keiner?
Ich kenne da nur eine Brutale Methode.
Project sichern, zB. in eine ZIP.
Dann eine Funktion nach dem anderen entfernen, und immer wieder probieren, ob es das Leek noch gibt.
So hab ich auch schon Leeks gefunden.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1650
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: [für mich hier gelöst] Großer Heap dump unfreed memory: wie vorgehen?

Beitrag von fliegermichl »

Ich habe so ein ähnliches Problem. In einer stark verschachtelten Funktion werden Klassen erzeugt und diese später dann auch normalerweise wieder freigegeben.
Von 2000 werden aber ca. 10 nicht wieder freigegeben und ich suche mir einen Wolf, wo genau das auftritt.

Jetzt habe ich geschaut, ob ich dem Heaptrace irgendwelche zusätzlichen Infos unterjubeln kann, die er mir in dem Dump mit ausgibt.
Dabei habe ich SetHeapExtraInfo gefunden. Wenn ich allerdings danach goggele, finde ich hier
eine offensichtlich veraltete Info.

Weiss jemand, wie das aktuell gelöst wird?

Edit: Ich habe es lösen können. Hier ein Code der funktioniert:

Code: Alles auswählen

Program heapex;

uses sysutils;

{ Program used to demonstrate the usage of heaptrc unit }

Var P1 : ^Longint;
    P2 : Pointer;
    I : longint;
    Marker : Longint;

Procedure SetMarker (P : pointer);

Type PLongint = ^Longint;

begin
  PLongint(P)^:=Marker;
end;

procedure DisplayMarker(var ptext : text; p : Pointer);
begin
  writeln(ptext, ' p:', IntToHex(ptrint(p), sizeof(pointer)), ' I: ', IntToHex(PLongInt(p)^, 8));
end;

Procedure  Part1;

begin
  // Blocks allocated here are marked with $FFAAFFAA = -5570646
  Marker := $FFAAFFAA;
  New(P1);
  New(P1);
  Dispose(P1);
  For I:=1 to 10 do
    begin
    GetMem (P2,128);
    If (I mod 2) = 0 Then FreeMem(P2,128);
    end;
  GetMem(P2,128);
end;

Procedure  Part2;

begin
  // Blocks allocated here are marked with $FAFAFAFA = -84215046
  Marker := $FAFAFAFA;
  New(P1);
  New(P1);
  Dispose(P1);
  For I:=1 to 10 do
    begin
    GetMem (P2,128);
    If (I mod 2) = 0 Then FreeMem(P2,128);
    end;
  GetMem(P2,128);
end;

begin
 SetHeapExtraInfo(SizeOf(Marker),@SetMarker, @DisplayMarker);
 Writeln ('Part 1');
 part1;
 Writeln('Part 2');
 part2;
end.
Nochmal Edit: Damit man die Arbeitsweise sehen kann, muss das Programm aus der Konsole gestartet werden.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1650
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: [für mich hier gelöst] Großer Heap dump unfreed memory: wie vorgehen?

Beitrag von fliegermichl »

Ich habe eine kleine Unit gebastelt, bei der man die Heapextra Informationen in seinem Programm nutzen kann:
defines.inc
muss dazu dann auch in der zu untersuchenden Unit eingebunden werden

Code: Alles auswählen

{$define useheapmarker}
heapextrainfo.pas

Code: Alles auswählen

unit heapextrainfo;
{$i defines.inc}
interface

uses
  SysUtils;

type
  PHeapMark = ^RHeapMark;
  RHeapMark = packed record
    HeapMarker : Longint;
    AllocCounter : Longint;
  end;

var
  HeapMark : RHeapMark;

implementation
uses heaptrc;

procedure SetMarker(p : Pointer);
begin
  PHeapMark(p)^.HeapMarker := HeapMark.HeapMarker;
  PHeapMark(p)^.AllocCounter := HeapMark.AllocCounter;
end;

procedure DisplayMarker(var ptext : text; p : Pointer);
begin
  writeln(ptext, 'ac: ', PHeapMark(p)^.AllocCounter, ' M: ', PHeapMark(p)^.HeapMarker);
end;

initialization
  SetHeapExtraInfo(SizeOf(RHeapMark), @SetMarker, @DisplayMarker);
end.
In der zu untersuchenden Unit kann dann beim allokieren eines Speichers diese verwendet werden. Der AllocCounter und Heapmarker erscheinen dann im Heapdump mit entsprechenden Werten.

Code: Alles auswählen

constructor TMyClass.Create;
begin
  {$ifdef useheapmarker}
   inc(HeapMark.AllocCounter);
   inc(HeapMark.HeapMarker)
  {$endif}
end;

destructor TMyClass.Destroy;
begin
  {$ifdef useheapmarker}
   dec(HeapMark.HeapMarker)
  {$endif}
end;
Da kann man dann schön sehen, der wievielte Aufruf von Create nicht mit einem entsprechenden Destroy zusammenpasst.

Antworten