Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi SetLength(DynArray,0) gibt den speicher nicht frei (https://www.delphipraxis.net/203636-setlength-dynarray-0-gibt-den-speicher-nicht-frei.html)

DelTurbo 6. Mär 2020 14:15

Delphi-Version: 2007

SetLength(DynArray,0) gibt den speicher nicht frei
 
Hi,
ich habe ein Problem. Ich habe einen Record der wie folgt aussieht.
Delphi-Quellcode:
type
  tEmailData = record
    InUse    :Boolean;
    ID       :Integer;
    HTML     :TStringList;
    TXT      :TStringList;
    Subject  :String;
    SendName :String;
end;
var
  EMailData    :array of tEmailData;
Ich setze die länge mir z.b. SetLength(EMailData,100). Wenn ich den nicht mehr brauche möchte ich den Speicher wieder frei haben. Ich durchlaufe dann erst eine Schleife und gebe die TStringList mit .Free wieder frei. Danach mache ich ein SetLength(EMailData,0).

Leider bleibt der speicher belegt. Auch ein EMailDatat:=nil hilft nicht weiter. Belege ich mit z.b. SetLength(EMailData,50) wird neuer Speicher genommen.

Was mache ich falsch. Ich suche schon im Netz 2 Tage lange. Ebenfalls hier im Forum. Ich bekomme es nicht hin das der Speicher wieder freigeben wird.

Vielen Dank im voraus

Stevie 6. Mär 2020 14:18

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Worauf basiert deine Annahme, dass der Speicher nicht freigegeben wird?

DelTurbo 6. Mär 2020 14:21

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Ich sehe das 1. am Taskmanager und irgendwann ist bekomme ich (Wenn ich es ein einer Schleife laufen lasse) Out of Memory.

DieDolly 6. Mär 2020 14:21

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Den Taskmanager kannst du direkt in die Tonne hauen.

DelTurbo 6. Mär 2020 14:26

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Mit dem Proccess Explorer von Sysinternals sehe ich auch das der Speicher nicht mehr Freigeben wird.

DelTurbo 6. Mär 2020 14:32

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Nachtrag: Das gleiche mit Freepascal unter Unix. Überprüft mit htop.

DenkDirNix 6. Mär 2020 14:33

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Die Strings müssen auch per User-Code freigegeben werden.

DelTurbo 6. Mär 2020 14:36

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Zitat:

Zitat von DenkDirNix (Beitrag 1459064)
Die Strings müssen auch per User-Code freigegeben werden.

Wie gebe ich die Frei? Auch mit z.b. SetLength(EMailData[i].Subject,0)?

DieDolly 6. Mär 2020 14:37

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Versuch die Dinger mal mit Dispose vorher freizugeben.

Ich habe auch sowas wie du irgendwo und ich nutze nur Dispose. Danach noch SetLength. Das mit den Strings halte ich für Unsinn.

DenkDirNix 6. Mär 2020 14:38

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Nö, ganz billig mit
Code:
Subject := '';
SendName := ''

Stevie 6. Mär 2020 14:40

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Zitat:

Zitat von DenkDirNix (Beitrag 1459064)
Die Strings müssen auch per User-Code freigegeben werden.

Was? Unfug, managed Types in Records werden implizit finalisiert, wenn das Array resized wird.

Zitat:

Zitat von DelTurbo (Beitrag 1459058)
Ich durchlaufe dann erst eine Schleife und gebe die TStringList mit .Free wieder frei.

Nur, damit es am Ende nicht an einem kleinen fehlenden s liegt - da sind 2mal TStringList in deinem Record, die gibst du beide frei, ja?

DieDolly 6. Mär 2020 14:40

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Zitat:

Was? Unfug
Meine Rede. So einen Quatsch habe ich auch noch nirgendwo gelesen.

Einfach die Record-Einträge mit Dispose vernichten und dann die Liste freigeben oder wenn du ein Array hast das auf 0 setzen.

DelTurbo 6. Mär 2020 14:41

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Klappt auch nicht. Es wird auch wesentlich mehr speicher belegt als in den zwei Strings ist.

DieDolly 6. Mär 2020 14:43

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Kommentier mal alles bis auf einen einzigen String in deinem Record und lass dann alles laufen.
Kommentier vorher aber auch alle Vorkommen der vorher kommentieren Datentypen überall.

Ich habe langsam den Eindruck, dass das Problem woanders ist.

Stevie 6. Mär 2020 14:43

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
FastMM rein und ausgeben lassen, was leakt - dieses Rumgerate anhand von Codeschnipseln ist nicht zielführend.

DelTurbo 6. Mär 2020 14:47

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Mit FastMM hab ich noch nie was gemacht. Müsste ich mir erstmal ansehen. Aber hier die schleife die frei geben soll.

Delphi-Quellcode:
procedure MemFreeHelper;
var
  i      :Integer;
begin
    for i:=Low(EMailData) to High(EMailData) do begin
      EMailData[i].InUse:=False;
      EMailData[i].HTML.Free;
      EMailData[i].TXT.Free;
    end;
    SetLength(EMailData,0);
end;

DieDolly 6. Mär 2020 14:49

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Zitat:

Mit FastMM hab ich noch nie was gemacht.
ReportMemoryLeaksOnShutdown := True; reicht für den Anfang auch.

Schmeiß mal HTML und TXT KOMPLETT raus und teste dann.

DelTurbo 6. Mär 2020 15:10

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Vielen vielen dank an euch. Ich hatte einen Fehler im befüllen des Arrays. :oops:
Nachtrag: Wenn ich einen TStringlist mit .Text befülle, muss ich vorher doch kein .Clear machen, oder?

Medium 6. Mär 2020 15:25

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Korrekt. .Clear ist im Grunde nichts anderes als .Text := '';

DelTurbo 6. Mär 2020 15:55

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Eine Frage habe ich noch. Wie finde ich die sachen die er hier anmeckert??? Ist mit DebugInfos usw. Kompiliert.

Code:
---------------------------
Unexpected Memory Leak
---------------------------
An unexpected memory leak has occurred. The unexpected small block leaks are:

1 - 12 bytes: String x 22
13 - 20 bytes: String x 3
21 - 28 bytes: String x 5
29 - 36 bytes: String x 5
37 - 44 bytes: String x 3
45 - 52 bytes: String x 3
53 - 60 bytes: String x 2
61 - 68 bytes: String x 2
69 - 76 bytes: String x 1
77 - 84 bytes: String x 3
149 - 156 bytes: String x 1

The sizes of unexpected leaked medium and large blocks are: 15916

---------------------------
OK  
---------------------------

Stevie 6. Mär 2020 16:00

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
FastMM4 von Github holen, einbinden, FullDebugMode in den Projektoptionen bei den Conditional defines hinzufügen, dafür sorgen, dass neben der exe die FullDebugMode.dll liegt (ist im FastMM4 Repo mit dabei). Dann landet ein detailiertes log in txt Format neben der exe, wo ein Callstack für jede geleakte Allokation aufgelistet ist.

DieDolly 6. Mär 2020 16:00

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Wenn du nichts weiter installieren willst und auch kein FastMM und sonst was (weniger Stress) , dann würde ich den Code komplett durchgehen.
Zum Beispiel das Programm starten, nichts machen und wieder schließen. Wenn dann beispielsweise schon Leaks kommen könnte man in dem Code suchen der ausgeführt wird, wenn man das Programm startet und beendet.

DelTurbo 6. Mär 2020 16:03

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Danke erstmal. Ich denke ich schaue mir mal das FastMM4 an. Kann ja nicht so schwer sein, hoffe ich.

Netten gruß an euch und schönes Wochenende.

haentschman 6. Mär 2020 17:09

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Moin...:P

Warum als Record und nicht als Klasse? :gruebel: PS: Ich mag keine Records. :oops: :wink:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages,
  System.SysUtils, System.Variants, System.Classes, System.Generics.Collections, System.Generics.Defaults,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
    TEmailData = class
    strict private
      FInUse: Boolean;
      FID: Integer;
      FHTML: TStringList;
      FTXT: TStringList;
      FSubject: string;
      FSendName: string;
    public
      constructor Create;
      destructor Destroy; override;
      property InUse: Boolean read FInUse write FInUse;
      property ID: Integer read FID write FID;
      property HTML: TStringList read FHTML write FHTML;
      property TXT: TStringList read FTXT write FTXT;
      property Subject: string read FSubject write FSubject;
      property SendName: string read FSendName write FSendName;
    end;

  TFormBlubb = class(TForm)
    procedure FormShow(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FEMailDataList: TObjectList<TEmailData>;
  public

  end;

var
  FormBlubb: TFormBlubb;

implementation

{$R *.dfm}

{ TEmailData }

constructor TEmailData.Create;
begin
  FHTML := TStringList.Create;
  FTXT := TStringList.Create;
end;

destructor TEmailData.Destroy;
begin
   FTXT.Free;
   FHTML.Free;
  inherited;
end;

{ TFormBlubb }

procedure TFormBlubb.FormCreate(Sender: TObject);
begin
  FEMailDataList := TObjectList<TEmailData>.Create;
end;

procedure TFormBlubb.FormDestroy(Sender: TObject);
begin
  FEMailDataList.Free;
end;

procedure TFormBlubb.FormShow(Sender: TObject);
var
  EmailData: TEmailData;
begin
  // Beispiele :-)

  // einfügen
  EmailData := TEmailData.Create;
  EmailData.InUse := True;
  // usw.
  FEMailDataList.Add(EmailData);

  // leeren
  FEMailDataList.Clear;
end;

end.
Link: http://docwiki.embarcadero.com/Libra...ns.TObjectList

:warn: Keine MemoryLeaks mehr. 8-)

DieDolly 6. Mär 2020 17:09

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Zitat:

Warum als Record und nicht als Klasse?
Ich selber benutze für sowas auch Records, weil die in der Autovervollständigung nicht diesen völlig unnötigen Ballast haben.

haentschman 7. Mär 2020 05:13

AW: SetLength(DynArray,0) gibt den speicher nicht frei
 
Moin...:P
[OT]
Zitat:

weil die in der Autovervollständigung nicht diesen völlig unnötigen Ballast haben
Kannst du das mal erklären? :gruebel:
[\OT]


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:43 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