Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Wie erkenne ich eigentlich ein Memory-Leak? (https://www.delphipraxis.net/183840-wie-erkenne-ich-eigentlich-ein-memory-leak.html)

pelzig 8. Feb 2015 21:40

Wie erkenne ich eigentlich ein Memory-Leak?
 
Der Titel sollte eigentlich schon alles sagen :wink:

Ich schau' im Task-Manager VORHER nach, wieviel RAM frei ist

- starte mein Programm, lasse es laufen und beende es wieder

und schaue im Task-Manger NACHHER wieder nach, wieviel RAM frei ist.

Wenn NACHHER=VORHER dann kein Leak?

Die Frage ist wirklich ernst gemeint!

MfG

Stevie 8. Feb 2015 21:50

AW: Wie erkenne ich eigentlich ein Memory-Leak?
 
Mit der Methode wirste nix finden. Denn ein Memory leak überlebt auf nem Windows mit NT Kernel nicht mehr die Dauer eines Processes (das war mal zu 95 oder 98 Zeiten so als nen fehlerhaftes Programm mal ebend deine komplette Windows Session zerhauen hat - aber jeder Boot tat gut)

Heutzutage lebt es also nur solange, wie dein Programm auch läuft. Ist aber schlimm genug, wenn du entweder nach einigen Stunden irgendwann in deinem 32bit Programm an die Speichergrenze kommst und es dir mit Fehlern weghagelt oder dein System nichts mehr für die anderen Prozesse übrig hat.

In neuen Delphi Versionen kannst du relativ einfach mit einem beherzten
Delphi-Quellcode:
ReportMemoryLeaksOnShutdown := True;
beim beenden einen Report bekommen, ob irgendwas im Verlauf deiner Anwendung nicht korrekt freigegeben wurde.

Für erweiterte Diagnose empfiehlt sich, die FastMM4 im full debug mode laufen zu lassen - siehe dazu z.B. diesen Artikel (und in den Kommentaren dort gibts auch noch den Link zu ner Coderage Session dazu)

pelzig 8. Feb 2015 22:35

AW: Wie erkenne ich eigentlich ein Memory-Leak?
 
Etwas neueres als die Delphi 7 Personal Edition will ich mir (finanziell und hobbybedingt) nicht antun.

Meine Programme erstellen i.A. nur das Hauptforumlar automatisch, der Rest wird bei Bedarf erzeugt.

Falls ich Dich richtig verstanden habe, ist beim Beenden des Programms inzwischen NACHHER immergleich VORHER?

Aber falls ich während meines Programmlaufs ein paarmal dynamisch (immer wieder) das gleiche Formular erzeuge und zerstöre, dabei im Task-Manager der RAM-Verbrauch aber nicht wieder auf den RAM-Startwert meines Programmes zurückgeht, habe ich ein Memory-Leak?

Hab' ich das richtig verstanden?

Danke @Stevie!

MfG

Stevie 8. Feb 2015 22:45

AW: Wie erkenne ich eigentlich ein Memory-Leak?
 
Zitat:

Zitat von pelzig (Beitrag 1289237)
Etwas neueres als die Delphi 7 Personal Edition will ich mir (finanziell und hobbybedingt) nicht antun.

Ok, aber FastMM nutzen geht trotzdem und ist nur zu empfehlen, auch wenn nur Hobby.

Zitat:

Zitat von pelzig (Beitrag 1289237)
Falls ich Dich richtig verstanden habe, ist beim Beenden des Programms inzwischen NACHHER immergleich VORHER?

Nunja, aufn RAM Verbrauch im Taskmanager achten ist so ne Sache und gibt nur grobe Anhaltspunkte - aber ja, dein Programm, wenn beendet kann dem Betriebssystem kein Speicher geklaut haben, denn Windows kümmert sich drum, dass es seine Resourcen zurückbekommt.

Zitat:

Zitat von pelzig (Beitrag 1289237)
Aber falls ich während meines Programmlaufs ein paarmal dynamisch (immer wieder) das gleiche Formular erzeuge und zerstöre, dabei im Task-Manager der RAM-Verbrauch aber nicht wieder auf den RAM-Startwert meines Programmes zurückgeht, habe ich ein Memory-Leak?

Gegenfrage, welcher Wert denn? Da gibt's nämlich mehrere. Ich verweis da mal auf eine ganz gute Erklärung.

Unterm Strich kann ich nur sagen, pack die FastMM in deine Anwendung und schau dir an, obs rummeckert. Alles andere wäre so als ob du mit nem abrollenden Seil und ner Sanduhr messen willst wie schnell du fährst ;)

pelzig 8. Feb 2015 23:04

AW: Wie erkenne ich eigentlich ein Memory-Leak?
 
Also statt "Seilrolle und Sanduhr" irgendwie versuchen, ein älteres FastMM (auftreiben und als "GPS") einzubinden?

OK, probier' ich mal.

Vielen Dank!

MfG

Stevie 8. Feb 2015 23:40

AW: Wie erkenne ich eigentlich ein Memory-Leak?
 
Zitat:

Zitat von pelzig (Beitrag 1289239)
älteres FastMM (auftreiben und als "GPS") einzubinden?

Die aktuellste Version sollte eigentlich auch für Delphi 7 noch funktionieren.

Frank Ranis 9. Feb 2015 08:03

AW: Wie erkenne ich eigentlich ein Memory-Leak?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

hatte öfter mal Objekte oder Speicher nicht richtig freigegeben , aber in diversen Schleifen immer wieder neu erzeugt und so ne Menge Leichen erzeugt.
Nun überwache ich meinen aktuellen Speicherbedarf mit 'GetHeapStatus.TotalAllocated' .
Einfach ab und an per Timer abfragen.
Kann man prima in einer Statusbar, fest eingebaut im Programm, ausgeben.
Quelltext und ZIP siehe unten.

Button 1 erzeugt eine Integer-Matrix [100,100].
Button 2 setzt die Matrix auf [0,0] zurück.

Gruß

Frank


Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    Button1: TButton;
    ListBox1: TListBox;
    Button2: TButton;
    StatusBar1: TStatusBar;
    procedure Timer1Timer(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

  Tint_vektor=array of integer;
  Tint_matrix=array of Tint_vektor;


var
  Form1: TForm1;
  m:tint_matrix;

implementation

{$R *.dfm}

// Speicher-Bedarf-Abfrage
procedure TForm1.Timer1Timer(Sender: TObject);
var Speicherinfo:THeapStatus;
begin
 // Aktuellen Speicherbedarf ausgeben
 speicherinfo:=GetHeapStatus;
 statusbar1.Panels[0].Text:=
              'Aktueller Speicherbedarf='+
              inttostr(speicherinfo.TotalAllocated)+
              ' Byte';
end;

// eine Integermatrix m[100,100] Global erzeugen
procedure TForm1.Button1Click(Sender: TObject);
var i,j:integer;
    s:string;
begin
 listbox1.Clear;
 setlength(m,100,100);
 for i:=0 to 99 do
  begin
   s:='';
   for j:=0 to 99 do
    begin
     m[i,j]:=i*j;
     s:=s+floattostr(m[i,j])+' ';
    end;
   listbox1.Items.Add(s);
  end;
end;

// die Integer-Matrix auf m[0,0] zurücksetzten
procedure TForm1.Button2Click(Sender: TObject);
begin
 setlength(m,0,0);
 listbox1.Clear;
end;

end.

himitsu 9. Feb 2015 08:51

AW: Wie erkenne ich eigentlich ein Memory-Leak?
 
Warum ist
Delphi-Quellcode:
m
eine globale Variable, obwohl es nur in TForm1 benutzt wird? (das gehört als Feld ins Private der TForm1)

Und dann ist das kein "richtiges" Speicherleck, denn dynamische Arrays sind gemanaged und werden automatisch freigegeben, wenn sie nur noch der Herr Niemand benutzt, genauso wie Strings, Variants und Interfaces.
Aber dafür gehören Variablen und eigentlich Alles nur in den Scope, in welchem sie verwendet werden.

In deinem Fall wird die
Delphi-Quellcode:
m
freigegeben, wenn die Unit entladen wird
und wenn man es in TForm verschiebt, dann wird es freigegeben, wenn die Form freigegeben wird.


Hier wird es schwerer, denn du müsstest den Speicher analysieren, während das Programm noch läuft, da die Speicherlecksuche bei Programmende natürlich zu spät ist.
Das genannte Ding, in meiner Signatur, hat da noch mehr Probleme. :stupid:
FastMM bietet z.B. eine MemoryMap

Frank Ranis 9. Feb 2015 10:02

AW: Wie erkenne ich eigentlich ein Memory-Leak?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo himitsu,

OK das mit dem Array war jetzt ein doofes Besipiel, wollte ja nur den aktuell benutzen Speicherbedarf ausgeben.

Nehmen wir das folgende Beispiel:

Ich habe zwei Buttons.
Mit Button3 erzeuge ich ein BMP.
Mit Button4 kille ich es wieder.

Drücke ich aber zwei oder noch mehr mal auf Button3, dann habe ich Bitmap-Leichen erzeugt, an die ich nicht mehr rannkomme.
Das kann man dann schön an der Anzeige 'Aktueller Speicherbedarf' sehen.
Ich komme dann nicht mehr auf den Speicher-Wert, den das Programm beim Starten hatte.

Gruß

Frank

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ComCtrls;

type

  Tint_vektor=array of integer;
  Tint_matrix=array of Tint_vektor;

  TForm1 = class(TForm)
    Timer1: TTimer;
    StatusBar1: TStatusBar;
    Button3: TButton;
    Button4: TButton;
    procedure Timer1Timer(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
   bmp:tbitmap;
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

// Speicher-Bedarf-Abfrage
procedure TForm1.Timer1Timer(Sender: TObject);
var Speicherinfo:THeapStatus;
begin
 // Aktuellen Speicherbedarf ausgeben
 speicherinfo:=GetHeapStatus;
 statusbar1.Panels[0].Text:=
              'Aktueller Speicherbedarf='+
              inttostr(speicherinfo.TotalAllocated)+
              ' Byte';
end;

// Bitmap erzeugen
procedure TForm1.Button3Click(Sender: TObject);
begin
 bmp:=tbitmap.Create;
end;

// Bitmap killen
procedure TForm1.Button4Click(Sender: TObject);
begin
 if bmp<>nil
  then
   begin
    bmp.Free;
    bmp:=nil;
   end;
end;

end.

himitsu 9. Feb 2015 10:25

AW: Wie erkenne ich eigentlich ein Memory-Leak?
 
Delphi-Referenz durchsuchenReportMemoryLeaksOnShutdown
http://www.delphipraxis.net/183846-f...nshutdown.html

PS:
.Free prüft intern bereits auf Self<>nil, bzw. aus Assigned(Self).
Und deine Prüfung geht kaputt, wenn es im Free knallt und dann kein nil gesetzt wird.

Delphi-Quellcode:
procedure TForm1.Button3Click(Sender: TObject);
begin
  Button4Click(nil); // Aufräumfunktion aufrufen, oder direkt FreeAndNil(bmp);
  bmp := TBitmap.Create;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  FreeAndNil(bmp);
end;

procedure TForm1.Form1Close(Sender: TObject);
begin
  Button4Click(nil); // Aufräumfunktion aufrufen, oder direkt FreeAndNil(bmp);
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:32 Uhr.
Seite 1 von 2  1 2      

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