Speicher freigeben

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
zummy
Beiträge: 17
Registriert: Mo 6. Nov 2006, 14:00

Beitrag von zummy »

Es ist zum Verrücktwerden....

Also es passiert folgendes:

Code: Alles auswählen

procedure Thauptfenster.startbuttonClick(Sender: TObject);
var primz: array of boolean;
begin
...
setlength(primz, spinedit1.value);  //bis zu 1000000000
Sieb(primz);
...
for z:=2 to spinedit1.Value do if primz[z] then ... ;//blabla
...
setlength(primz,1);
 //alternativ primz:=nil; oder: finalize(primz);
...
end;
 
procedure Thauptfenster.Sieb(var a: array of boolean);
var bis,c,i,w:integer;
begin
bis:=...;
for c:=1 to bis do a[c]:=true;
w:=...;
for c:=1 to w do
    begin
    if a[c] then
       begin
       i:=c*c;
              repeat
              a[i]:=false;
              inc(i,c);
              until i>bis;
       end;
    end;
end;
An anderen Stellen taucht primz nicht auf.

Nachdem die Prozedur Thauptfenster.startbuttonClick komplett durchgelaufen ist, müsste doch der Speicher freigegeben werden. Aber bei keiner der drei Varianten passiert das!

Es ist auch kein Fehler in der Anzeige des Taskmanagers. Mein Programm belegt fast den ganzen Speicher und andere Prozesse müssen dann auf die Auslagerungsdatei zurückgreifen... :(

Benutzeravatar
theo
Beiträge: 10857
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Frag doch mal in der FPC Liste nach oder mach einen Bug-report.

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Mit dem fpc 2.1.1 hab ich genau das gestern probiert und es hat super funktioniert.

var
a : array of word;

procedure TForm1.Button1Click(...);
begin
Setlength(a,999999);
end;

procedure TForm1.Button2Click(...);
begin
a := nil;
//Setlength(a,0);
//Finalize(a);
end;

3,4 mb Speicherbelegung.
Das ist der Code nach klick auf den ersten Button 199 mb Speicherverbrauch.
Nach klick auf den 2. wieder 3,4 mb.
mit allen 3 Varianten.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Beitrag von Euklid »

Prima. Ist schon bekannt, wann die RV vom fpc 2.1 rauskommen wird?

iaby
Beiträge: 24
Registriert: Mi 25. Okt 2006, 19:48

Beitrag von iaby »

mal angenommen ich hab ein dynamisches array das 1000 einträge hat. Jetzt will ich den 1001 eintrag hinzufügen! Wie stelle ich das jetzt am besten an? Denn wenn ich SetLength(myArray, 1001) mache, dann ist der speicherbedarf überproportional groß, aber ein nil kann ich ja auch nicht zuweisen, weil ich dann alle daten im Array verliere!
Jemand eine Idee?

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

@iaby
Hä ?
Du willst 1001 Einträge in deinem Array bist aber nicht gewillt für 1001 Einträge Speicher zuzuweisen versteh ich dich richtig ?
Sorry das ist mir zu hoch wenn du 1001 Einträge brauchst brauchst du auch für 1001 Einträge Speicher, geht nunmal nicht anders.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

monta
Lazarusforum e. V.
Beiträge: 2809
Registriert: Sa 9. Sep 2006, 18:05
OS, Lazarus, FPC: Linux (L trunk FPC trunk)
CPU-Target: 64Bit
Wohnort: Dresden
Kontaktdaten:

Beitrag von monta »

Ich denke eher, er hat nach einer Möglichkeit gesucht, die Größe zu ändern, welche weniger Overhead produziert, als Setlength.

Aber zumindest mir ist da keine bekannt, lasse mich da aber gerne korigieren.

iaby
Beiträge: 24
Registriert: Mi 25. Okt 2006, 19:48

Beitrag von iaby »

Ok, ich erklärs nochmal kurz richtig:

Ich habe den eindruck, dass wenn ich ein array auf die größe von 1000 bring, und zwar immer mit SetLength(Array, high(Array) + 2), dass er dann Speicher für 1000Fakultät Daten braucht.
Wenn ich also mein array von 1000 auf 1001 vergrößere, dann braucht er speicher für 2001 Daten. (angenommen davor war nicht schon öfters ein SetLength!)

ovidius
Beiträge: 86
Registriert: Mo 11. Sep 2006, 12:54
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Bremen

Beitrag von ovidius »

ch habe den eindruck, dass wenn ich ein array auf die größe von 1000 bring, und zwar immer mit SetLength(Array, high(Array) + 2), dass er dann Speicher für 1000Fakultät Daten braucht.

Wenn ich also mein array von 1000 auf 1001 vergrößere, dann braucht er speicher für 2001 Daten. (angenommen davor war nicht schon öfters ein SetLength!)
Also das bestimmt nicht. Du hast nicht mal 1000! Bit in Deinem Rechner. (1000! = 1000 * 999 * 998 * ... * 1)

Dass das Programm 2001 Speicherzellen braucht, liegt daran, dass der Garbage Collector den freigegebenen Speicher nicht sofort wieder an das System zurückgibt. Dafür kann es mehrere Gründe geben. Meiner Meinung nach wird das Freigeben wahrscheinlich erst beim Verlassen von Prozeduren/Funktionen durchgeführt, um gute Geschwindigkeit des Programms zu erzielen.

Hinzugefügt:
Lesen bildet bekanntlich: Laut FreePascal Doku wird der nicht mehr benötigte Speicher für dynamische Felder immer erst am Ende der Prozedur bzw. Funktion freigegeben. Ich entschuldige mich auch schon mal vorsorglich für den Ausdruck Garbage Collector, aber mir ist nicht klar, ob es ein besseres Wort dafür gibt. Ein Garbage Collector im eigentlichen Sinn ist es ja nicht.

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Also ich habs eben mal probiert, und hatte eigentlich den eindruck, das es linear mit der Anzahl der Elemente ansteigt.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Beitrag von Euklid »

habe folgende Frage:

[Edit]
theo hat geschrieben:Primz ist ein Dynamisches Array und wird durchaus mit Finalize oder Nil freigegeben.
[/Edit]
theo hat geschrieben:Es wird auch automatisch freigegeben, wenn keine Referenz mehr daruf besteht.
Was bedeutet das konkret? Etwa, dass lokal definierte dynamische Arrays nach Prozedurende automatisch gelöscht werden und daher nicht zwingend freigegeben werden müssen?

Euklid
Zuletzt geändert von Euklid am Sa 5. Apr 2008, 14:30, insgesamt 1-mal geändert.

monta
Lazarusforum e. V.
Beiträge: 2809
Registriert: Sa 9. Sep 2006, 18:05
OS, Lazarus, FPC: Linux (L trunk FPC trunk)
CPU-Target: 64Bit
Wohnort: Dresden
Kontaktdaten:

Beitrag von monta »

Wo hat Theo das denn geschrieben? Hier im Thread ja nicht.

Das ist doch eigentlich das, was der GC bei Java, .NET usw. macht. Aber bei Pascal gibts doch keinen. Wie werden die dann automatisch freigegeben?
Johannes

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Beitrag von Euklid »

monta hat geschrieben:Wo hat Theo das denn geschrieben? Hier im Thread ja nicht.
Theo hat das in seinem zweiten Beitrag dieses Threads geschrieben - hätte ich eben dazuschreiben sollen.
Es geht thematisch um die Freigabe des Speicherplatzes von dynamischen Arrays. Ist z.B. test ein dynamisches array, so lässt sich der Speicher durch
test:=nil;
freigeben. Meine frage ist: Ist diese Zeile am Ende einer Prozedur überhaupt notwendig, wenn test lokal definiert ist?

monta
Lazarusforum e. V.
Beiträge: 2809
Registriert: Sa 9. Sep 2006, 18:05
OS, Lazarus, FPC: Linux (L trunk FPC trunk)
CPU-Target: 64Bit
Wohnort: Dresden
Kontaktdaten:

Beitrag von monta »

:oops: ich hab übersehen, das der Thread zwei Seiten hatte
Johannes

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Beitrag von Euklid »

Euklid hat geschrieben:Es geht thematisch um die Freigabe des Speicherplatzes von dynamischen Arrays. Ist z.B. test ein dynamisches array, so lässt sich der Speicher durch
test:=nil;
freigeben. Meine frage ist: Ist diese Zeile am Ende einer Prozedur überhaupt notwendig, wenn test lokal definiert ist?
Da meine Programme in denen ich dynamische Arrays verwende laut heaprc Speicherleichen am laufenden Band produzieren kann man diese Frage letzten Endes wohl nur mit JA beantworten.

EDIT:

Hierbei scheint es sich aber um einen BUG zu handeln. In der FreePascal-Referenz steht zu dynamischen Arrays geschrieben:
The memory will be disposed of at the exit of the current procedure or function.
Was so viel heißt, wie: Im Normalfall sollten die dynamischen Arrays tatsächlich "automatisch" freigegeben werden, wenn die betreffende Prozedur oder Funktion verlassen wird.

Antworten