Autor Beitrag
Logikmensch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 390

Win XP
Delphi 2007 Prof., XE2, XE5
BeitragVerfasst: Mo 23.01.06 07:42 
Hallo liebe Delphi-Forum-Freunde!

ein etwas verspätetes frohes neues Jahr! Und nochmals Dank für all die nützlichen Tipps, die ihr hier schreibt! :-)

Ich habe mir verschiedene Delphi-Bücher zugelegt, in denen das Thema "Freigabe eines Strings oder dynamischen arrays" z.T. sehr unterschiedlich beschrieben wird. Die einen schreiben, dass ein String oder dynamisches Array, welches z.B. mit SetLength erzeugt wurde, mit SetLength(<array>,0) freigegeben wird, andere meinen, dass <array>=nil die Freigabe erledigt. Ich habe seither innerhalb von Prozeduren und Funktionen ein array of <variable> auch immer nur mit SetLength(<array>,0) auf Null-Länge gesetzt und die NIL-Setzung unterlassen und gehofft, dass dadurch auch der reservierte Speicher komplett freigegeben wird. Nun habe ich Sorge, dass das vielleicht nicht genügt.

Andererseits muss man einfache Strings beim Verwenden in Prozeduren und Funktionen ja vor dem Verlassen derselben auch nicht auf Null-Länge oder NIL setzen, das sollte doch der Rahmencode automatisch tun:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure summe(anzahl:integer);
var
  a:array of integer
  s:string;
begin
  setlength(a,anzahl);
  s:='test test test';
  .....
  .....
  setlength(a,0);   und/oder  a:=nil;
//setlength(s,0); und/oder s:=nil; ist hoffentlich wirklich unnötig
end;


Vielleicht arbeitet dieser Rahmencode aber auch nur für Strings und nicht für dynamische Arrays.
Wie ist es denn nun? Hat jemand dazu konkrete Informationen? Wie gibt man ein dynamisches array so frei,
dass der Speicher wirklich freigegeben wird? Oder kann man es sich komplett sparen, so wie bei Strings?

Für sachdienliche Hinweise bedanke ich mich im Voraus!

Claus.
0xCC
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 150



BeitragVerfasst: Mo 23.01.06 07:46 
verwende mal fastmm4 dann siehst du selber was freigegeben wird und was nicht.
einfach fastmm4 als erstes in die uses klausel des prj files
ist ein leak kriegst du ne meldung beim schliessen des progs
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Mo 23.01.06 08:14 
@0xCC: fastmm4 findet mein D2005 PE und D6 Prof. nicht. Wo bekommt man die her?

@Logikmensch: Das man das mit einer nil-Setzung freigibt ist völliger Schwachsinn. Wenn du das machst erreichst du zwar den Speicherinhalt nicht mehr, aber es ist immer noch im RAM gespeichert, also nicht frei gegeben. Die nil-Setzung bringt nach dem Freigeben etwas, denn dann kann man überprüfen ob es auf nil gesetzt ist und weiß dadurch, dass der Speicher komplett frei gegeben ist.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 23.01.06 10:19 
Moin!

Ähm, AFAIK ist die Delphi-OH da aber ziemlich eindeutig: dyn. Array := NIL; gibt den Speicher frei! :wink:

cu
Narses
Logikmensch Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 390

Win XP
Delphi 2007 Prof., XE2, XE5
BeitragVerfasst: Mo 23.01.06 11:43 
Hallo nochmal,

ihr seht, es gibt da doch verschiedene Meinungen dazu. FastMM4 kenne ich auch nicht bzw. kennt mein Delphi (2005, Enterprise, allerdings ohne .NET-Verwendung) ebenfalls nicht - scheint ein (kostenloses) Tool oder Kompo eines Drittanbieters zu sein.

Alternativ könnte ich natürlich auch den Debugger verwenden, um es ganz sicher abzuprüfen, aber ich hatte gehofft, dass es jemand ganz, ganz sicher weiß. :-)

@OxCC: Ich hatte es bisher auch so gesehen, dass ein einfaches NIL-setzen nur den Zeiger auf Null setzt, aber den Speicherbereich allokiert belässt. Möglicherweise hat Borland da aber eine besondere Free-Routine eingebaut, wenn man <dyn. Array> = nil verwendet.
Meine Frage ging sogar soweit, dass man es ja vielleicht sogar ganz weglassen könnte (zumindest in Procedures oder Functions), weil es bei Strings ja auch nicht nötig ist.

Ich belasse die Frage mal offen, vielleicht kennt sich jemand noch mit den Delphi (7 und 2005) interna soweit aus, dass er sicher sagen kann, was da beim NIL-setzen oder beim Verlassen der Procedure nun mit dem allokierten lokalen dyn. Array passiert.

Liebe Grüße und schon jetzt vielen Dank für die Antworten!

Claus.
ulrix
Hält's aus hier
Beiträge: 9

Win XP, SuSE Linux
Delphi 2009
BeitragVerfasst: Mo 23.01.06 11:52 
Weder das zuruecksetzen von Strings noch von dyn. Arrays ist notwendig! (Uebrigens IST ein String ein dyn. Array!!!).

Die Speicherfreigabe (Object Pascal sei dank) passiert voellig automatisch (nicht wie in JAVA, aber durch hinzugefuegten terminierungscode vom compiler).


Es gibt zwei moeglichkeiten, wie Arrayspeicher freigegeben wird:

*) Beim zuruecksetzen mit SetLength:
z.B.:
Zuerst SetLength(Arr, 1024); und danach SetLength(Arr, 50);

*) oder am Ende des Code Blockes, in dem das Array definiert wurde.
z.B.:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure Foo; 
var
  s          : String;  
  TestArr    : array of Integer;
  
begin
  s := 'hello';
  SetLength(TestArr, 1024);
  //...
end;    //<-- Hier wird 's' und 'TestArr' frigegeben !!!!!!


Fuer dich heisst es, dass du in kleinen funktionen keine Arrays freigeben brauchst. Jedoch solltest du auch bedenken, dass sie wirklich erst am ende freigegeben werden, dass heist wenn ein Objekt ein dyn. Array enthaelt und wird es erst nach der freigabe des Objektes freigegeben !!!! => Arrays mit SetLength 0 - setzen, wenn sie nicht mehr beoetigt werden!!!!

lg

Moderiert von user profile iconChristian S.: Code- durch Delphi-Tags ersetzt
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 23.01.06 11:54 
Strings und dynamische Arrays kann man mit Finalize freigeben:
Zitat:

Finalize simply sets all long strings to empty and all variants and interfaces to Unassigned, thus properly releasing any memory that was referenced by the long strings and variants.
Tastaro
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 414
Erhaltene Danke: 23



BeitragVerfasst: Mo 23.01.06 15:49 
In der D7 Onlinehilfe steht doch alles zum Thema "Dynamische Arrays".
Anlegen, Kopieren, Abschneiden, Freigeben.

Für Eilige zum Thema "Freigeben"
Zitat:
Um ein dynamisches Array freizugeben, weisen Sie einer Variablen, die das Array referenziert, den Wert nil zu, oder Sie übergeben die Variable an Finalize. Beide Methoden geben das Array unter der Voraussetzung frei, dass keine weiteren Referenzen darauf vorhanden sind. Dynamische Arrays werden immer freigegeben, sobald ihr Referenzzähler auf null fällt.


Ich für meinen Teil setze jedes dynamische Array, das ich mit setlength anlege immer auf nil, sobald ich es nicht mehr brauche. Hat sich für mich aus Gründen der Übersichtlichkeit bewährt.

Beste Grüße
Tastaro
Logikmensch Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 390

Win XP
Delphi 2007 Prof., XE2, XE5
BeitragVerfasst: Di 24.01.06 07:15 
Titel: dynamische arrays freigeben mit NIL oder Finalize
Hallo!

Vielen Dank für die zahlreichen Infos zum Thema. @ulrix: Ich dachte mir schon, dass da eine automatische Freigabe arbeitet, wenn der aktuelle Block verlassen wird. Danke an alle für die zahlreichen Zitate - ich hatte die z.T. auch schon gelesen, aber da die Literatur es mitunter ein wenig anders widergab, kam ich ein bisschen ins Grübeln.

Fazit: Es ist höchstwahrscheinlich völlig unnötig, ein NIL oder Finalize auszuführen, weil dies am Blockende sowieso erledigt wird. Aber auch zwischenzeitlich kann es nötig sein, einen Speicher zu leeren, der lange vor dem Verlassen des Blocks nicht mehr benötigt wird.
Aber: Aus Gründen der Programmierpraxis sollte man sicherlich irgendein Verfahren anwenden, um auf "saubere Weise" selber die Finalisierung von dyn. Arrays durchzuführen, selbst wenn der Compiler hinterher nochmal nachkontrolliert. Wahrscheinlich schon wegen der Portierbarkeit des Quellcodes auf andere Compiler, die das vielleicht nicht tun.
Ich habe mich jetzt auch für <array>=nil entschieden, weil es, wie Tastaro sagt, einfach auch schön ausschaut. ;-)

Vielen lieben Dank für die für mich wichtige Diskussion!

Claus.
0xCC
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 150



BeitragVerfasst: Mi 25.01.06 21:01 
user profile iconHeiko hat folgendes geschrieben:
@0xCC: fastmm4 findet mein D2005 PE und D6 Prof. nicht. Wo bekommt man die her?

google fragen ^_^

ich habe die erfahrung gemacht wenn ich eine funktion habe die mir ein dynamisches array zurückliefert gibt es leaks, wenn ich diese variable nicht nach gebrauch manuell mit setlength(x,0) freigebe.