![]() |
SetLength(dyn. array, 0) vs. Finalize() vs. nil
Hallo Community,
Ich habe mal im Forum rechergiert, welche Möglichkeiten es gibt, dyn. arrays freizugeben. Dabei bin ich auf die o.g. Prozeduren bzw. nil gestoßen und bin jetzt leicht verwirrt. Ich zitiere einfach mal die verschiedenen Aussagen: Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
Wie sollte ich jetzt die beiden dyn. arrays sauber freigeben, sodass der gesamte Speicherbereich wieder an Windows übergeben wird?
type
TStringArray = array of String; var Partition : array of TTreeNode; Dirs : TStringArray; [...] SetLength(Partition,10); SetLength(Dirs,3); [...] // Freigeben beider dyn. arrays Btw: Wie müsste ich ein array of "record" korrekt freigeben, wenn dieser u.a. Short- bzw. LongStrings (= unbegrenzte Angabe), Integers und TreeNodes enthalten würde? |
Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
Zitat:
Zum Thema: Ich kann zu meiner vorherigen Aussage trotzdem nur nochmals ausführen, was ich festgestellt habe: 1. Dynamischen Arrays einfach NIL zuweisen gibt diese nicht sauber frei und werden als verlorener Speicher bei Speichertestern ausgegeben (Delphi 4 und Delphi 5) 2. lokale dynamische Arrays in Proceduren hinterlassen !sporadisch! Speicherlecks, wenn nach dem SetLength() kein Finalize() kommt (Delphi 4) 3. direktes anwenden von Finalize auf ein dynamisches Array führt zu einer ungenügenden Array Freigabe, es bleiben im Schnitt 8 Bytes nicht freigegeben zurück (Delphi 5). Bei höheren Delphiversionen mag das alles klappen und ein vernünftiger Weg sein. |
Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
Also nach deiner Auffassung sollte ich bei dem Beispiel die dyn. arrays so freigeben?
Delphi-Quellcode:
Muss ich nicht die einzelnen TreeNodes aus dem array "Partition" seperat freigeben oder übernimmt gerade Finalize() diese Aufgabe für mich?
SetLength(Partition,0);
SetLength(Dirs,0); Finalize(Partition); Finalize(Dirs); |
Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
Ein dynamisches Array mit dem base type TTreeNode ist recht ungewöhnlich. Grundsätzlich lebt ein TTreeNode in der Obhut von TTreeNodes und dieser Container verwaltet die Nodes von der Wiege bis zur Bahre. Finalize(), angewandt auf das dynamische array, weiß nichts von diesem Doppelleben der Nodes und darf auch gar nichts darüber wissen.
Grüße vom marabu |
Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
Jo, deine Aussage war richtig. Es ist wirklich ungewöhnlich und sinnlos, solch ein array zu deklarieren, wie ich in meinem Code bemerkt habe. Habe das jetzt korrigiert.
Zu Finalize(): Diese Prozedur wird also nur auf Variablen mit undefinierbarer Länge angewandt, wie z.B. auf long-strings, variants usw.? D.h. es gibt keinen Grund, diese Prozedur auf array of Extended oder array of String[200] bzw. Shortstring loszulassen, richtig? Noch mal zu records:
Delphi-Quellcode:
Da in diesem record eine Variable mit undefinierter Länge (= String) enthalten ist, müsste ich diesen doch beim Freigeben des arrays mit Finalize() leeren, oder? Und wenn ja, wie genau?
type
PGroupData = ^TGroupData; TGroupData = record GroupID : Word; ShouldExpand : Boolean; S : String; end; var TestArrayT : array of TGroupData; // wird eher selten benutzt, nicht wahr? TestArrayP : array of PGroupData; Wenn ich jetzt falsch liege, erklärt mir bitte das Gegenteil mithilfe der Beipiele. Das hilft mir ungemein. |
Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
Zitat:
Zitat:
Delphi-Quellcode:
type
PGroupData = ^TGroupData; TGroupData = record GroupID : Word; ShouldExpand : Boolean; S : String; end; var TestArrayT : array of TGroupData; // wird eher selten benutzt, nicht wahr? TestArrayP : array of PGroupData; Zitat:
Für deinen zweiten Array-Typ bin ich im Augenblick überfragt. Ich vermute sehr stark, dass keine Finalisierung statt finden wird, aber ich müsste es untersuchen um sicher zu sein. marabu |
Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
Vielen Dank für die detailierten und klärenden Erläuterungen, Muetze1 und marabu.
Zusammenfassend kann man also sagen: Mit SetLength initialisierte dyn. arrays sollten mit (in der Reihenfolge) 1.) SetLength(array, 0); und 2a.) Finalize(array); bzw. 2b.) Finalize(array, Length(array)); freigegeben werden. 2a) wird benutzt, wenn ein array of vordefinierte Typen (= string, Integer, Real, Boolean usw.) verwendet wird. 2b) wird benutzt, wenn ein array of TRecord verwendet wird. Erbitte Bestätigung für diese Zusammenfassung. Danke. |
Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
Ich sehe keinen Interpretationsspielraum in dieser Frage. "Dynamische Typen" sind die internen Typen LongString, WideString, Variant, Array, Record, Interface und DynArray. Wenn v eine Variable ist und ihr Typ zu den zuvor genannten zählt, dann ist Finalize(v) bzw. Finalize(v, Length(v)) angesagt. Bei Arrays folgt dann SetLength(v, 0), bei den anderen Typen v := nil - so ist man auf der sicheren Seite.
marabu |
Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
Ok, ok...
eins noch: Gerade an dieser Stelle kreuzen sich 2 Meinungen: Zitat:
Zitat:
|
Re: SetLength(dyn. array, 0) vs. Finalize() vs. nil
Hallo Nogge,
wenn SetLength(v, 0) zuerst ausgeführt wird, dann kommt Finalize(v, Length(v)) doch nach der Feier.
Delphi-Quellcode:
Sonntagsgrüße vom marabu
type
TItem = packed record Name: string; Amount: integer; end; var Items: array of TItem; i: integer; begin // es werden 3 mal 8 Byte vom heap besorgt SetLength(Items, 3); // die einzelnen Items werden initialisert for i := Low(Items) to High(Items) do with Items[i] do begin // der pointer "Name" wird auf einen dynamischen // Speicherblock gesetzt, der 6 Byte Nutzdaten zzgl. // Verwaltungsinformationen (Längenzähler, term char, etc. // umfasst. Name := 'Name-' + IntToStr(Succ(i)); // nativer Datentyp, kein heap beteiligt Amount := Succ(Random(5)); end; end; // Alle Zeiger "Name" werden auf nil gesetzt // der garbage collector beobachtet den auf // 0 gehenden refence count und deallokiert // den von den strings auf dem heap belegten Speicher Finalize(Items, Length(Items)); // Die 3 * 8 Byte müssen auch noch an den heap // zurückgegeben werden. SetLength(Items, 0); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:44 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