Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi VST Speicherleak (https://www.delphipraxis.net/109036-vst-speicherleak.html)

hanspeter 23. Feb 2008 08:09


VST Speicherleak
 
Hallo,

ich erzeuge die Knoten für ein VST:

Delphi-Quellcode:
 PTreeData = ^TTreeData;
  TTreeData = record
    ID         : integer;
    Single     : boolean; // Einzelliste
    FixID      : integer;
    Kategorie  : Char;
    Untergrp   : Char;
    isUntergrp : boolean;
    Index      : integer;
    Title      : string;
    isKategorie : boolean;
  end;
Die Initialisierung

Delphi-Quellcode:
VST.NodeDataSize := sizeof(TTreeData);
 VST.BeginUpdate;
 VST.Clear;
Bei VST.Free bleibt zum Programmende ein Speicherleak mit einer Anzahl nicht freigegebener Strings.

Was muss ich noch freigeben?

Für einen Tip dankbar.

Gruß
Peter

Hawkeye219 23. Feb 2008 08:27

Re: VST Speicherleak
 
Hallo Peter,

du solltest auf jeden Fall das Ereignis OnFreeNode behandeln und dort durch einen Aufruf von Delphi-Referenz durchsuchenFinalize die Freigabe des Speichers veranlassen, etwa so:

Delphi-Quellcode:
procedure TForm1.VSTreeNode (Sender: TBaseVirtualTree; Node: PVirtualNode);
var
  NodeData : PTreeData;
begin
  NodeData := Sender.GetNodeData(Node);
  Finalize (NodeData^);
end;
Das Ereignis wird für jeden sichtbaren Knoten automatisch ausgelöst. Es könnte eventuell notwendig sein, schon beim Erzeugen der Knoten einen späteren Aufruf zu erzwingen:

Delphi-Quellcode:
Node := VST.AddChild(nil);
...
VST.InvalidateNode (Node); // erzwingt Aufruf von OnFreeNode bei Freigabe
Gruß Hawkeye

hanspeter 23. Feb 2008 09:02

Re: VST Speicherleak
 
Zitat:

Zitat von Hawkeye219
Hallo Peter,

du solltest auf jeden Fall das Ereignis OnFreeNode behandeln und dort durch einen Aufruf von Delphi-Referenz durchsuchenFinalize die Freigabe des Speichers veranlassen, etwa so:

Gruß Hawkeye

Danke für den Tip.
Habe ich ausprobiert, bringt aber nichts.
Als Leak werden ausschließlich Strings protokolliert.

Gruß
Peter

sakura 23. Feb 2008 09:04

Re: VST Speicherleak
 
Im OnFree musst Du die strings Deines Records auf nil (bei Strings '') setzen.

...:cat:...

Hawkeye219 23. Feb 2008 09:25

Re: VST Speicherleak
 
Hallo sakura,

Zitat:

Zitat von sakura
Im OnFree musst Du die strings Deines Records auf nil (bei Strings '') setzen.

Das ist eigentlich die Aufgabe von Finalize:

Zitat:

Zitat von Delphi-Hilfe zu Finalize
[...]Finalize setzt einfach alle langen Strings auf einen leeren Wert und alle Varianten und Schnittstellen auf Unassigned und sorgt somit für die ordnungsgemäße Freigabe des betreffenden Speichers.[...]

Ich vermute eher, dass das OnFreeNode-Ereignis nicht für alle Baumknoten ausgelöst wird, weil einige Knoten niemals angezeigt wurden. In diesem Fall hilft die oben erwähnte Methode InvalidateNode, die unter anderem den Knoten als "initialisiert" markiert und somit dafür sorgt, dass für den betreffenden Knoten ein OnFreeNode-Ereignis ausgelöst wird.

Gruß Hawkeye

hanspeter 23. Feb 2008 09:44

Re: VST Speicherleak
 
Zitat:

Zitat von sakura
Im OnFree musst Du die strings Deines Records auf nil (bei Strings '') setzen.

...:cat:...

Das mache ich bereits bringt aber nichts.

Hier die Freigabe

Delphi-Quellcode:
procedure TForm5.VirtualStringTree1FreeNode(Sender: TBaseVirtualTree;
  Node: PVirtualNode);
var
  NodeData : PTreeData;
begin
  NodeData := Sender.GetNodeData(Node);
  NodeData.Title := '';
  Finalize (NodeData^);
end;
und hier das Erzeugen des Baumes:

Delphi-Quellcode:
procedure Add(Gruppe: Char;ID : integer; Titel:string);
  var
    i    : integer;
    sel  : boolean;
    Node1 : PVirtualNode;
  begin
    sel := true;
    for i := 0 to Lst.Count -1 do
    begin
      zg := TDruckliste(Lst[i]);
      if zg.Untergrp = Gruppe then
      begin
        if Sel then // Bei erstmaligen Auftreten Gruppenkopf anlegen
        begin
          Child           := VST.AddChild(nil); // VST.AddChild(Node);
          VST.InvalidateNode (Child);
          ptr             := VST.GetNodeData(Child);
          ptr^.ID         := ID;
          ptr^.Title      := Titel;
          ptr^.Single     := false;
          ptr^.Untergrp   := Gruppe;
          ptr^.FixID      := zg.FixRep;
          ptr^.isUntergrp := true;
          sel             := false;
        end;
          Node1            := VST.AddChild(Child);
           VST.InvalidateNode (Node1);
          ptr             := VST.GetNodeData(Node1);
          ptr^.ID         := zg.RID;
          ptr^.Title      := zg.Titel;
          ptr^.Single     := false;
          ptr^.Untergrp   := Gruppe;
          ptr^.FixID      := zg.FixRep;
          ptr^.isUntergrp := false;
          zg.Node         := Node1;
          VST.CheckType[node1] := ctCheckBox;
          Node1.CheckType := ctCheckBox;
          Node1.CheckState := csUncheckedNormal;
          VST.CheckState[node1] := csUncheckedNormal;
      end;
    end;
    VST.Invalidate;
  end;
Gruß
Peter

Hawkeye219 23. Feb 2008 10:39

Re: VST Speicherleak
 
Peter, ersetze einmal die Aufrufe von InvalidateNode durch Aufrufe von ReinitNode:

Delphi-Quellcode:
// VST.InvalidateNode (Node1);
VST.ReinitNode (Node1, False);
Du solltest dir auch überlegen, ob es sinnvoll ist, Kopien der bereits im Speicher befindlichen Daten in den Baum zu stecken. Wäre es nicht einfacher, einen Verweis in den Knoten abzulegen und über diesen bei Bedarf auf die Daten zuzugreifen?

Gruß Hawkeye

hanspeter 23. Feb 2008 11:08

Re: VST Speicherleak
 
Zitat:

Zitat von Hawkeye219
Peter, ersetze einmal die Aufrufe von InvalidateNode durch Aufrufe von ReinitNode:

Delphi-Quellcode:
// VST.InvalidateNode (Node1);
VST.ReinitNode (Node1, False);
Du solltest dir auch überlegen, ob es sinnvoll ist, Kopien der bereits im Speicher befindlichen Daten in den Baum zu stecken. Wäre es nicht einfacher, einen Verweis in den Knoten abzulegen und über diesen bei Bedarf auf die Daten zuzugreifen?

Gruß Hawkeye

Hallo,
erst mal vielen Dank für den Tip.

ReinitNode beseitigt das Speicherleak!

Die Daten lade ich eigentlich nur temporär in den Speicher und gebe sie nach der Initialisierung des Treeview wieder frei.
Das Treeview zeigt kategorisierte Drucklisten zur Auswahl an. Hat maximal 30 Einträge.
Das Speicherleak war insofern ein Problem, da ich das Treeview programmabhängig öfter mit unterschiedlichen Daten initialisiere.

Ich überlege jetzt allerdings, ob ich in den Nodedaten nur einen Index ablege und den Titel in einer Stringliste extern unterbringe.
Also nochmals vielen Dank für die Unterstützung.

Mit Gruß
Peter

generic 23. Feb 2008 12:31

Re: VST Speicherleak
 
Ihr macht euch das etwas kompliziert hier.
Das Speicherleck wird von den String kommen.

Du hast 2 einfache Möglichkeiten.
1) du nutzt Shortstrings im Record (Title:string[255]);
2) im onFreeNode-Ereignis setzt den den Titel im Record einfach auf "". Dann kannst du auch die Largestrings nutzen.

Im DP Stammstisch 3 Video habe ich die Problematik kurz erwähnt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:01 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz