| Autor |
Beitrag |
DeadlyAppearance
      
Beiträge: 113
Win 7
Delphi 2010 Arch., C# VS 2008
|
Verfasst: Do 18.12.08 15:19
Hallo zusammen.
Und zwar habe ich das Problem, dass mein Programm immer mehr Speicher belegt und nicht mehr frei gibt.
Ich habe nun den Problembereich gefunden und soweit vereinfacht, dass ich es hier mal posten kann.
Wie es scheint, liegt das Problem bei MySation.MyItemList := TObjectList.Create;.
Was das ganze machen soll?
Es gibt eine List mit "Stationen", welche aus einem Station-Objekt besteht, welches wieder eine List an Item-Objekten beinhaltet.
Rein von der Funktionalität funktioniert es tadenlos, nur beim Freigeben des Speichers scheint etwas schief zu laufen.
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: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41:
| TMyStation = class(TObject) StationName : Integer; MyItemList: TObjectList; end;
TMyItem = class(TObject) StationName, ItemName, ItemJump : Integer; ItemPrice : Double; end;
procedure TForm1.Button2Click(Sender: TObject); var MyList : TObjectList; MySation : TMyStation; MyItem : TMyItem; i : Integer; begin MyList := TObjectList.Create;
MyItem := TMyItem.Create; try MyItem.ItemName := 12; MyItem.ItemPrice := 10.12; except FreeAndNil(MyItem); end;
try for I := 0 to 999 do begin MySation := TMyStation.Create; MySation.MyItemList := TObjectList.Create; MySation.StationName := 1234; MySation.MyItemList.Add(MyItem); MyList.Add(MySation); end; finally FreeAndNil(MyList); end; end; |
Ich hoffe ihr könnt mir weiter helfen, da ich schon seit einigen Stunden am rumdocktern bin und das Problem nicht finden kann.
Danke
_________________ Als du auf die Welt kamst, weintest du, und um dich herum freuten sich alle. Lebe so, daß, wenn du die Welt verläßt, alle weinen und du allein lächelst.
|
|
AXMD
      
Beiträge: 4006
Erhaltene Danke: 7
Windows 10 64 bit
C# (Visual Studio 2019 Express)
|
Verfasst: Do 18.12.08 15:23
Du gibst am Ende nur die Liste frei, nicht aber die einzelnen Items, die sich darin befinden
AXMD
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 18.12.08 15:34
Das sollte eigentlich auch nicht nötig sein, denn OwnsObjects ist standardmäßig ohne Angabe im Konstruktor ja True.
Aber du könntest Clear vorher aufrufen, vielleicht ändert das etwas.
In der Delphi Doku hört es sich so an als würden die Objekte auch freigegeben, wenn die Liste zerstört wird, in der FreePascal Doku hört es sich nur so an, wenn die Objekte entfernt oder Clear aufgerufen wird.
Ich werde mal schauen was genau dabei passiert.
|
|
DeadlyAppearance 
      
Beiträge: 113
Win 7
Delphi 2010 Arch., C# VS 2008
|
Verfasst: Do 18.12.08 15:35
Ahh, k.
Ich dachte, dies passiert automatisch beim Freigeben des übergeordneten Objektes.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| TMyStation = class(TObject) StationName : Integer; MyItemList: TObjectList; destructor Destroy; override; end;
destructor TMyStation.Destroy; begin MyItemList.Free; inherited Destroy; end; |
Bei dieser Lösung kommt eine "Ungültige Zeigeroperation" Fehlermeldung.
Wie mache ich das richtig?
_________________ Als du auf die Welt kamst, weintest du, und um dich herum freuten sich alle. Lebe so, daß, wenn du die Welt verläßt, alle weinen und du allein lächelst.
|
|
DeddyH
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Do 18.12.08 15:38
Wo wird MyItemList denn erzeugt? Normalerweise ja im Constructor. Und ja, TObjectList gibt seine enthaltenen Objekte automatisch frei, wenn OwnsObjects nicht explizit auf false gesetzt wurde.
|
|
DeadlyAppearance 
      
Beiträge: 113
Win 7
Delphi 2010 Arch., C# VS 2008
|
Verfasst: Do 18.12.08 15:43
Vorher habe ich MyItemList im der Schleife nach dem Create von MySation aufgerufen.
Jetzt habe ich es mal in den constructor gepackt.
Aber leider frisst das Programm auch weiterhin bei jedem Buttonclick immer mehr kB.
Also gibt er die Liste nicht korrekt frei.
Da es sich ja nur um ein kurzen Quelltext handelt, könnt ihr diesen ja gerne mal bei euch kurz einbinden, vielleicht sehr ihr dann wo genau das Problem liegt.
_________________ Als du auf die Welt kamst, weintest du, und um dich herum freuten sich alle. Lebe so, daß, wenn du die Welt verläßt, alle weinen und du allein lächelst.
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 18.12.08 15:49
Ich habe mir jetzt deinen Code angeschaut und konnte das Problem nicht reproduzieren.
Es wächst nur die Speicherbelegung im Taskmanager und das liegt am Speichermanager von Delphi.
Alle Objekte werden wieder freigegeben bis auf eines: Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| MyItem := TMyItem.Create; try MyItem.ItemName := 12; MyItem.ItemPrice := 10.12; except FreeAndNil(MyItem); end; | Und dass das nicht freigegeben wird ist ja klar, weil du es nur in except freigibst und nicht immer.
|
|
DeadlyAppearance 
      
Beiträge: 113
Win 7
Delphi 2010 Arch., C# VS 2008
|
Verfasst: Do 18.12.08 15:51
MyItem kann ich ja nicht freigeben, da es ja an meinem Stationobjekt hängt.
Aber durch das zerstören des Stationobjektes sollte ja auch das Item rausfliegen.
Und bezüglich Taskmanager, wenn ich das Programm in einer weit größeren Schleife laufen lasse bin ich irgend wann bei
100MB und mehr, also scheint das ja doch nen Problem mitm freigeben zu sein.
_________________ Als du auf die Welt kamst, weintest du, und um dich herum freuten sich alle. Lebe so, daß, wenn du die Welt verläßt, alle weinen und du allein lächelst.
|
|
AXMD
      
Beiträge: 4006
Erhaltene Danke: 7
Windows 10 64 bit
C# (Visual Studio 2019 Express)
|
Verfasst: Do 18.12.08 15:53
DeadlyAppearance hat folgendes geschrieben : | MyItem kann ich ja nicht freigeben, da es ja an meinem Stationobjekt hängt.
Aber durch das zerstören des Stationobjektes sollte ja auch das Item rausfliegen. |
Eben deshalb habe ich ja vorhin geschrieben, dass du jedes Item der Liste getrennt freigeben solltest. Ist doch zumindest einen Versuch wert, oder nicht  ?
AXMD
|
|
DeadlyAppearance 
      
Beiträge: 113
Win 7
Delphi 2010 Arch., C# VS 2008
|
Verfasst: Do 18.12.08 15:56
Das war ja mein Versuch wie oben gezeigt im destructor, doch leider funktioniert dieser nicht.
Deshalb die bitte, wie mache ich das?
_________________ Als du auf die Welt kamst, weintest du, und um dich herum freuten sich alle. Lebe so, daß, wenn du die Welt verläßt, alle weinen und du allein lächelst.
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 18.12.08 15:56
DeadlyAppearance hat folgendes geschrieben : | MyItem kann ich ja nicht freigeben, da es ja an meinem Stationobjekt hängt.
Aber durch das zerstören des Stationobjektes sollte ja auch das Item rausfliegen. |
Aaaah, jetzt verstehe ich, das hab ich übersehen...
Nein, dadurch fliegt es nicht heraus, das musst du im Destruktor machen, ich schaue mir das nochmal an, auch deinen Code dazu.
|
|
DeadlyAppearance 
      
Beiträge: 113
Win 7
Delphi 2010 Arch., C# VS 2008
|
Verfasst: Do 18.12.08 16:00
jaenicke hat folgendes geschrieben : | DeadlyAppearance hat folgendes geschrieben : | MyItem kann ich ja nicht freigeben, da es ja an meinem Stationobjekt hängt.
Aber durch das zerstören des Stationobjektes sollte ja auch das Item rausfliegen. | Aaaah, jetzt verstehe ich, das hab ich übersehen...
Nein, dadurch fliegt es nicht heraus, das musst du im Destruktor machen, ich schaue mir das nochmal an, auch deinen Code dazu. |
Oha, danke dir.
Nun sind wir schon mal nen Schritt weiter
Mein Beispiel oben mit dem destructor funktioniert leider nicht.
Bin sehr gespannt, wie man das nun korrekt macht.
_________________ Als du auf die Welt kamst, weintest du, und um dich herum freuten sich alle. Lebe so, daß, wenn du die Welt verläßt, alle weinen und du allein lächelst.
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 18.12.08 16:13
DeadlyAppearance hat folgendes geschrieben : | | Mein Beispiel oben mit dem destructor funktioniert leider nicht. |
Doch, und genau das ist das Problem  .
Du fügst das selbe Item in mehrere ObjectLists ein, und beim ersten freigegebenen TMyStation Objekt wird es im Destruktor wie du ihn jetzt hattest freigegeben. Davon wissen die anderen ObjectLists aber nix.
Wenn du für jedes Einfügen in die Liste ein neues Objekt erzeugst, dann funktioniert das auch. Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| try for I := 0 to 999 do begin MySation := TMyStation.Create; MySation.MyItemList := TObjectList.Create; MySation.StationName := I; MyItem := TMyItem.Create; try MyItem.ItemName := 12; MyItem.ItemPrice := 10.12; MySation.MyItemList.Add(MyItem); except FreeAndNil(MyItem); end; MyList.Add(MySation); end; finally FreeAndNil(MyList); end; |
|
|
DeadlyAppearance 
      
Beiträge: 113
Win 7
Delphi 2010 Arch., C# VS 2008
|
Verfasst: Do 18.12.08 16:31
Also mit der Fehlermeldung lag daran wie du gesagt hast.
War mein Fehler in dem Umbauen fürs Beispiel.
Aber...
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: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54:
| TMyStation = class(TObject) StationName : Integer; MyItemList: TObjectList; constructor Create; destructor Destroy; override; end;
TMyItem = class(TObject) StationName, ItemName, ItemJump : Integer; ItemPrice : Double; end;
constructor TMyStation.Create; begin MyItemList := TObjectList.Create; end;
destructor TMyStation.Destroy; begin MyItemList.Free; inherited Destroy; end;
procedure TForm1.Button2Click(Sender: TObject); var MyList : TObjectList; MySation : TMyStation; MyItem : TMyItem; i : Integer; begin MyList := TObjectList.Create;
try for I := 0 to 999 do begin MySation := TMyStation.Create; MySation.MyItemList := TObjectList.Create; MySation.StationName := I; MyItem := TMyItem.Create; try MyItem.ItemName := 12; MyItem.ItemPrice := 10.12; MySation.MyItemList.Add(MyItem); except FreeAndNil(MyItem); end; MyList.Add(MySation); end; finally FreeAndNil(MyList); end; end; |
...es frisst sich immer noch voll  .
_________________ Als du auf die Welt kamst, weintest du, und um dich herum freuten sich alle. Lebe so, daß, wenn du die Welt verläßt, alle weinen und du allein lächelst.
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 18.12.08 16:38
Du erzeugst die ObjectList ja auch doppelt  , einmal im Konstruktor und einmal in der Zeile danach.
|
|
DeadlyAppearance 
      
Beiträge: 113
Win 7
Delphi 2010 Arch., C# VS 2008
|
Verfasst: Do 18.12.08 16:42
Hrhr, danke, nun gehts.
Aber warum muss ich nun in desctructor die MyItemList frei geben?
Warum wird diese nicht mit zerstört, wenn ich das Objekt lösche, an dem diese hängt?
Möchte das gerne für die Zukunft verstehen 
_________________ Als du auf die Welt kamst, weintest du, und um dich herum freuten sich alle. Lebe so, daß, wenn du die Welt verläßt, alle weinen und du allein lächelst.
|
|
jaenicke
      
Beiträge: 19341
Erhaltene Danke: 1752
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 18.12.08 16:50
DeadlyAppearance hat folgendes geschrieben : | | Warum wird diese nicht mit zerstört, wenn ich das Objekt lösche, an dem diese hängt? |
Bei einer ObjectList passiert das ja nur, weil diese im Destruktor (in TList) Clear aufruft und daraufhin die Objekte aus der Liste entfernt und gelöscht werden. Die Klasse, die du benutzt, weiß also, dass es eine Liste von Objekten gibt und diese ggf. entfernt werden müssen.
Deine eigenen Objekte sind aber von TObject abgeleitet. Dieses kann ja nicht wissen was du für eigene Sachen in dein Objekt steckst, und dementsprechend kann dieser existierende Destruktor dir nicht die Arbeit abnehmen.
Die Programmierer der TList und TObjectList haben genau dieses Freigeben auch im Konstruktor selbst programmiert. Und als Programmierer deiner Klasse TMyStation musst du das auch tun. 
|
|
DeddyH
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Do 18.12.08 16:56
Und das doppelte Instanziieren könnte nicht passieren, wenn man die ObjectList als ReadOnly-Property definiert.
|
|
DeadlyAppearance 
      
Beiträge: 113
Win 7
Delphi 2010 Arch., C# VS 2008
|
Verfasst: Do 18.12.08 17:16
Ja dann mal vielen Dank in die Runde für die schnelle Hilfe.
Wünsche euch noch einen schönen Abend.
_________________ Als du auf die Welt kamst, weintest du, und um dich herum freuten sich alle. Lebe so, daß, wenn du die Welt verläßt, alle weinen und du allein lächelst.
|
|
|