Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Speicherlag bei Übergabe eines Objects vom Thread
Flamefire - Sa 20.09.08 19:59
Titel: Speicherlag bei Übergabe eines Objects vom Thread
Hallo,
habe folgendes:
Ich benutze die Struktur, die wir hier erstellt haben:
Klick [
http://www.delphi-forum.de/topic_DatenStruktur+fuer+BackupTool_86458.html]
Im wesentlichen also:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| constructor TOrdner.Create(const AName: String = ''; AOwner: TOrdner = NIL); begin inherited Create; FName := AName; FOwner := AOwner; FOrdner := TObjectlist.Create; FDateien := TStringList.Create; if Assigned(FOwner) then FOwner.Ordner.Add(Self); end; destructor TOrdner.Destroy; begin FreeAndNil(FDateien); FreeAndNil(FOrdner); inherited; end;
procedure TOrdner.Free(ARemove:Boolean=false); begin If(self<>nil) then begin If ARemove and (FOwner<>nil) then FOwner.FOrdner.Extract(self); Destroy; end; end; |
Jetzt lasse ich in einem eigenen Thread das ganze füllen (verschiedene Ordner und dateien in die Listen darunter...)
Dann übergebe ich das ganze mittels Synchronize an eine weitere Klasse.
Von:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| procedure TSuchThread.SyncFertig; begin FFertig:=true; SyncStatus; FSyncFertig(FOrdner);end; |
Nach:
Delphi-Quelltext
1: 2: 3: 4: 5:
| procedure TAufgabe.SourceScanFertig(AOrdner:TOrdner); begin FOSource.Free(); FOSource:=AOrdner; end; |
Dabei bemerke ich, dass nach mehrmaligem Ausführen des Suchvorgangs der Speicher, den das Programm benutzt wächst.
Sollte aber nicht sein.
Wenn ich das mache:
Delphi-Quelltext
1: 2: 3: 4:
| procedure TAufgabe.SourceScanFertig(AOrdner:TOrdner); begin AOrdner.Free(); end; |
Ist alles i.o.
Also ist diese Struktur das Problem. Aber warum? Ich gebe sie doch frei und setze die dann neu.
Jmd Ideen?
Flamefire - Mi 24.09.08 09:29
Keiner ne Idee was da sein könnte?
Es wird doch kein weiterer speicher verbraucht beim "kopieren" der TOrdner struktur, da ja nur der pointer kopiert wird.
Ich versteh das nicht... :?!?: :?!?: :?!?: :crying:
Lossy eX - Mi 24.09.08 16:39
Also ich kann Anhand der kleinen Codestückchen wirklich nur raten. Aber ich denke mal sehr stark, dass die Instanz AOrdner die an SourceScanFertig übergeben wird, irgendwie übrig bleibt. Du sagst ja selber, dass kein Speicherloch entsteht, wenn AOrdner direkt in SourceScanFertig gelöscht wird. Allerdings, wenn du FOSource freigibst und dann AOrdner zuweist, dann entsteht eines. Mit dem ersten Freigeben wird ja nur die Instanz gelöscht die vorher auf FOSource zugewiesen wurde. Und wenn du dann eine neue auf FOSource zuweist, dann existiert die so lange weiter bis auch diese gelöscht wird. Und wenn du FOSource beim Freigeben der TAufgabe Instanz nicht mit freigibst, dann bleibt sie erhalten.
Du kannst/solltest dir auch mal FastMM4 anschauen. Der hat neben einem verbesserten Speichermanager auch noch die Möglichkeit sich Speicherlöcher anzeigen zu lassen. So würdest du sofort sehen ob was übrig geblieben ist und vor allem was und wo es erstellt wurde.
Ich denke das wurde dir vermutlich schon mal gesagt, aber ich tue es trotzdem noch mal. Deutsche Bezeichner an sich ja schon schlimm aber in einem Bezeichner Deutsch und Englich zu mischen übertrifft das noch. Das ist echt schon ein bisschen grusselig. :P
Flamefire - Mi 24.09.08 17:11
Ja zugegeben meine bezeichner sind seltsam...aber was solls...ich komm damit klar ^^
mal zur veranschaulichung:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| FOSource:=nil;
... FSuchSource:=TSuchThread.Create(FSSource,1,SourceScanFertig); ... procedure TAufgabe.SourceScanFertig(AOrdner:TOrdner); begin FOSource.Free(); FOSource:=AOrdner; end;
...
FSuchSource:=TSuchThread.Create(FSSource,1,SourceScanFertig); ... procedure TAufgabe.SourceScanFertig(AOrdner:TOrdner); begin FOSource.Free(); FOSource:=AOrdner;end; -->Speicher leak! |
Das ist jetzt kein code sonder der prinzipielle ablauf.
Also: Den alten Ordner gebe ich frei und nehme den neuen. Es existiert also immer ein Ordner-Objekt (nur beim start existiert keins)
Da die Daten immer gleich sind (es wird das gleiche Verzeichnis eingelesen) sollte sich der verwendete speicher nicht erhöhen.
tut er aber.
Hab mit eurekalog schonma versucht, da was zu finden, aber zeigt nix an.
anzeigen tut er aber was nach "AllocMem(10000)"; also hat es funktioniert.
ich sehe einfach nichts was das verursachen könnte
Lossy eX - Do 25.09.08 09:14
Also Anhand von dem Pseudocode/Schema kann man nicht sagen ob das richtig ist. Denn ich für meinen Teil weiß nicht wie lange die TAufgabe gültig ist und was mit dem zugewiesenen FOSource passiert. Wenn du beim Freigeben von TAufgabe das FOSource nicht löscht, dann hast du ein Speicherloch. Wenn du es doch löscht, dann sollte keines existieren.
Wenn du bereits einen Speichertester deines Vertrauens hast laufen lassen und der keinen Fehler angezeigt hat (obwohl Delphi von Hause aus eigentlich immer einen Fehler hat), dann wird es an etwas anderem liegen. Wenn Delphi Speicher benötigt, dann wird das in Blöcken von Windows angefordert und auf die aktuelle und folgende Aufgaben verteilt. Solch ein Block kann natürlich nur dann freigegeben werden, wenn alle Referenzen darauf gelöscht wurden. Und wenn zufällig gerade ein delphi interenes Objekt Speicher haben wollte, dann kann es sein, dass obwohl du alles gelöscht hast der Speicherverbrauch im Windows nicht wieder runter geht. Das ist sogar nicht selten der Fall, weswegen der Speicherverbrauch im Windows nicht zum Feststellen von Löchern brauchbar ist. Sondern nur dafür wie viel deine Anwendung wirklich beanschlagt.
Was du machen kannst ist mal ein Stresstest. Also nicht 1-2 Verzeichnisse einlesen sondern 100-200. Also das geht dann auch nur automatisiert. Und wenn der Speicherverbrauch dann kontinuierlich ansteigt, dann solltest du mal das von mir erwähnte FastMM4 ausprobieren. Erwarte aber auch da nicht, dass der Speicherverbrauch wieder auf den Anfang zurück geht. Selbst ein Objekt was noch so klein ist kann einen Speicherblock als benutzt markieren. Wenn du pech hast kann dir das auch bei mehr als nur einem Block passieren.
Flamefire - Do 25.09.08 10:31
Als Stresstest habe ich den windows ordner einlesen lassen. (ca 4000 Ordner)
und dass 100 mal
nach verschiedenen anpassungen (wie explizitem setzen von FOrdner=nil; im destructor des threads) stelle ich das fest, was du gesagt hast: der speicherverbrauch geht hoch bis auf einen bestimmten punkt und schwankt dann dort (+-100b)
sieht also so aus, als wäre das problem gelöst.
vielen dank.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!