AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Array korrekt freigeben

Ein Thema von woodie · begonnen am 23. Sep 2025 · letzter Beitrag vom 25. Sep 2025
Antwort Antwort
Seite 2 von 3     12 3      
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.835 Beiträge
 
Delphi 12 Athens
 
#11

AW: Array korrekt freigeben

  Alt Gestern, 13:34
:=nil ist einfacher und schnell/optimaler, da hier nur freigegeben wird, während SetLength erst noch bissl prüft und dann was macht und auch anderes machen könnte (z.B. wenn nicht 0 reingegeben)
Fakten-Checker gefällig?

Dieser Code
Delphi-Quellcode:
  
  SetLength(lFilterArray, 0);
  lFilterArray := nil;
wird zu diesem Binary

Delphi-Quellcode:
Project1159.dpr.44: SetLength(lFilterArray, 0);
00D4EBDA 8D45FC lea eax,[ebp-$04]
00D4EBDD 8B152CDED300 mov edx,[$00d3de2c]
00D4EBE3 E8A4B5FEFF call $00d3a18c
Project1159.dpr.45: lFilterArray := nil;
00D4EBE8 8D45FC lea eax,[ebp-$04]
00D4EBEB 8B152CDED300 mov edx,[$00d3de2c]
00D4EBF1 E896B5FEFF call $00d3a18c
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
freimatz
Online

Registriert seit: 20. Mai 2010
1.525 Beiträge
 
Delphi 11 Alexandria
 
#12

AW: Array korrekt freigeben

  Alt Gestern, 14:01
Könnte man hier nicht auch lFilterArray := []; verwenden? Finde ich irgendwie schöner.
  Mit Zitat antworten Zitat
QuickAndDirty

Registriert seit: 13. Jan 2004
Ort: Hamm(Westf)
2.076 Beiträge
 
Delphi 12 Athens
 
#13

AW: Array korrekt freigeben

  Alt Gestern, 14:33
Delphi-Quellcode:
Project1159.dpr.44: SetLength(lFilterArray, 0);
00D4EBDA 8D45FC lea eax,[ebp-$04]
00D4EBDD 8B152CDED300 mov edx,[$00d3de2c]
00D4EBE3 E8A4B5FEFF call $00d3a18c
Project1159.dpr.45: lFilterArray := nil;
00D4EBE8 8D45FC lea eax,[ebp-$04]
00D4EBEB 8B152CDED300 mov edx,[$00d3de2c]
00D4EBF1 E896B5FEFF call $00d3a18c
Also ist es doch an sich das selbe? nur finalize ist anders aber ich verstehe nicht ganz warum ich es brauche.
In welcher situation fuktioniert ":= nil" nicht und finalize muss benutzt werden? Speziell für Arrays und Records.
Andreas
Nobody goes there anymore. It's too crowded!
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.835 Beiträge
 
Delphi 12 Athens
 
#14

AW: Array korrekt freigeben

  Alt Gestern, 15:43
Hier ist das ausführlich erklärt - man muss es aber auch ganz lesen: System.Finalize

Wichtig ist dabei folgende Sequenz:
Zitat:
Wenn auf eine dynamische Variable folgende Bedingungen zutreffen, ist ein Aufruf von Finalize erforderlich, um die Variable vor ihrer Deallozierung zu finalisieren.

Die Variable wird nicht mit der Standardprozedur Dispose (sondern z.B. mit FreeMem) freigegeben.

Die Variable enthält lange Strings, Varianten und Interfaces, die nicht alle leer sind bzw. den Wert Unassigned haben.
Es müssen beide Bedingungen zutreffen, also insbesondere die dynamische Erzeugung/Freigabe und dann auch nur wenn dabei kein New/Dispose verwendet wird.

Im konkreten Fall sind alle deklarierten Array-Variablen, die über SetLength oder ein Copy ihren Speicher bekommen, nicht davon betroffen, da der Compiler weiß was damit zu tun ist und den nötigen Aufräumcode entsprechend anlegt.

Ich kann mich nicht erinnern, wann ich das letzte Mal wirklich ein Finalize schreiben musste.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
QuickAndDirty

Registriert seit: 13. Jan 2004
Ort: Hamm(Westf)
2.076 Beiträge
 
Delphi 12 Athens
 
#15

AW: Array korrekt freigeben

  Alt Gestern, 16:39
Ich muss einen Record der lange strings enthält aber nicht wirklich mit finalize freigeben?

Wenn ich den Record mit getmem erzeugt habe vielleicht doch?
Andreas
Nobody goes there anymore. It's too crowded!
  Mit Zitat antworten Zitat
Benutzerbild von dummzeuch
dummzeuch

Registriert seit: 11. Aug 2012
Ort: Essen
1.754 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#16

AW: Array korrekt freigeben

  Alt Gestern, 17:42
Ich muss einen Record der lange strings enthält aber nicht wirklich mit finalize freigeben?

Wenn ich den Record mit getmem erzeugt habe vielleicht doch?
Ja, genau das.
Thomas Mueller
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.776 Beiträge
 
Delphi 12 Athens
 
#17

AW: Array korrekt freigeben

  Alt Gestern, 20:58
Könnte man hier nicht auch lFilterArray := []; verwenden? Finde ich irgendwie schöner.
Das geht jetzt/inzwischen.
Früher ging es ja nicht, dass man dynamische Arrays so zuweisen konnte.

Wäre wohl angebracht nachzusehn, ob die CodeOptimierung auch hier funktioniert.
Beim SetLength war es mal so, dass es nicht / nicht immer optimiert wurde und dann wirklich der Aufruf auf System._DynArraySetLength erfolgte.

[edit]
Jupp, sieht gut aus. (ist wohl direkt passende CompilerMagic ... nicht erst die CodeOptimierung, denn im Debug-Profil ist die ja aus)
Delphi-Quellcode:
Unit3.pas.29: SetLength(TestArray, 3);
008042B3 6A03 push $03
008042B5 8D45F8 lea eax,[ebp-$08]
008042B8 B901000000 mov ecx,$00000001
008042BD 8B1568428000 mov edx,[$00804268]
008042C3 E8008FE2FF call $0062d1c8 // System._DynArraySetLength
008042C8 83C404 add esp,$04

Unit3.pas.30: TestArray := [];
008042CB 8D45F8 lea eax,[ebp-$08]
008042CE 8B1568428000 mov edx,[$00804268]
008042D4 E81390E2FF call $0062d2ec // System._DynArrayClear

Unit3.pas.31: SetLength(TestArray, 0);
008042D9 8D45F8 lea eax,[ebp-$08]
008042DC 8B1568428000 mov edx,[$00804268]
008042E2 E80590E2FF call $0062d2ec // System._DynArrayClear

Unit3.pas.32: TestArray := nil;
008042E7 8D45F8 lea eax,[ebp-$08]
008042EA 8B1568428000 mov edx,[$00804268]
008042F0 E8F78FE2FF call $0062d2ec // System._DynArrayClear
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (Gestern um 21:06 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.835 Beiträge
 
Delphi 12 Athens
 
#18

AW: Array korrekt freigeben

  Alt Gestern, 21:46
Wenn ich den Record mit getmem erzeugt habe vielleicht doch?
Beispiel:
Delphi-Quellcode:
procedure ExDynRecord;
type
  PMyRec = ^TMyRec;
  TMyRec = record
    MyString: string;
  end;
var
  MyRec: TMyRec; { die Deklaration sorgt dafür, dass MyRec finalisiert wird }
  MyPtr: PMyRec;

  procedure Log(LogIdx: Integer);
  begin
    if MyPtr = nil then
      Writeln(LogIdx, ': ', StringRefCount(MyRec.MyString))
    else
      Writeln(LogIdx, ': ', StringRefCount(MyRec.MyString), ':', StringRefCount(MyPtr.MyString));
  end;

begin
  MyRec.MyString := 'Hello World';
  UniqueString(MyRec.MyString); { Referenzzähler auf 1 setzen (wegen des Literals wäre das sonst -1) }
  MyPtr := nil;
  Log(0);

  MyPtr := @MyRec; { ein Record - ein String }
  Log(1);
  { hier ist keine Finalisierung für MyPtr^ notwendig }
  MyPtr := nil;
  Log(2);

  New(MyPtr);
  Log(10);
  MyPtr^ := MyRec; { überträgt den Inhalt von MyRec in den dynamischen Record. Der Referenzzähler des String wird erhöht.}
  Log(11);
  Dispose(MyPtr);
  Log(12);
  { auch hier ist keine Finalisierung für MyPtr^ notwendig }
  MyPtr := nil;
  Log(13);

  GetMem(MyPtr, Sizeof(TMyRec));
  Log(20);
  MyPtr^ := MyRec; { s.o. }
  Log(21);

  { aber hier ist eine Finalisierung für MyPtr^ notwendig, andernfalls bleibt der string bestehen }
// Finalize(MyPtr^);
  Log(22);
  FreeMem(MyPtr);
  Log(23);

  MyRec.MyString := '';
  Log(30);
end;
Ausgabe ohne Finalize:
Code:
0: 1
1: 1:1
2: 1
10: 1:0
11: 2:2
12: 1:0
13: 1
20: 1:0
21: 2:2
22: 2:2
23: 2:2
30: 0:1
Ausgabe mit Finalize:
Code:
0: 1
1: 1:1
2: 1
10: 1:0
11: 2:2
12: 1:0
13: 1
20: 1:0
21: 2:2
22: 1:0
23: 1:0
30: 0:0
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.776 Beiträge
 
Delphi 12 Athens
 
#19

AW: Array korrekt freigeben

  Alt Gestern, 22:02
GetMem und GetMemory reservieren Speicher, aber dieser ist nicht zwangsläufig mit 0 initialisiert.
Du solltest danach also besser auch noch ein Initialize drüber jagen.
So wie das Finalize vor dem FreeMem.

Beim AllocMem ist es dagegen garantiert immer mit 0 initialisiert, also ein FillChar/ZeroMemory ist integriert, und somit "quasi" das Initialize bereits mit enthalten. (wenn auch nicht wirklich, aber es wirkt so, so lange es kein ManagedRecord-Initialiize gibt)

Beim New und Dispose sind dagegen Initialize und Finalize bereits integriert.


Im Prinzip ist AllocMem wie ein Objekt-Feld (oder fast wie globale Variable),
GetMem/GetMemory wie eine lokale non-managed Variable (der Zufall schlägt böse zu)
und New+Dispose wie eine lokale managed Variable, bzw. wie Create und Destroy zum Objekt-Feld.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (Heute um 09:42 Uhr)
  Mit Zitat antworten Zitat
woodie

Registriert seit: 30. Sep 2020
8 Beiträge
 
#20

AW: Array korrekt freigeben

  Alt Heute, 07:34
ich habe im Beispiel nur alle 3 Varianten aufgeführt:

Code:
Setlength(AArray,0);
Finalize(AArray);
AArray:=nil;
um 'sicher' zu gehen, normalerweise nutze ich nur Setlength(AArray,0);

Die Frage ist aber immer noch, warum es mir von FastMM5 als Leak angezeigt wird.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:38 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz