![]() |
Re: Objekt in Array kopieren und anschließend freigeben
Für solche Sachen enthält die TObjectList schließlich "OwnsObjects". In weiser Voraussicht haben sie das standardmäßig schon auf true gesetzt. Ist schon recht interessant, was man damit alles zusammenbauen kann. Und kaum einer weiß es.
|
Re: Objekt in Array kopieren und anschließend freigeben
Zitat:
|
Re: Objekt in Array kopieren und anschließend freigeben
Um mal auf deine Originalfragen noch einzugehen:
Zitat:
Zitat:
Zitat:
Prinzipiell ist es aber auch völlig richtig TObjectList einzusetzen. Ein Array ist für das was du dort vor hast recht ungeeignet. |
Re: Objekt in Array kopieren und anschließend freigeben
Hallo.
Danke für eure Antworten. Ich habe jetzt den Array entfernt und durch eine abgeleitete Objektliste ersetzt. Jetzt erhalte ich eine AV, die ich absolut nicht verstehe. Wenn ich mit die Objektliste x befülle und freigebe, funktioniert alles. Gebe ich die Objektliste x in eine Funktion, die eine zweite Liste y erstellt, kommt eine AV bei Freigabe von x:
Delphi-Quellcode:
Zur schnellen Rekonstruktion noch folgender Zusatzcode mit Deklarationen:
function MachWas(Input: TSubmissionObjectList): TSubmissionObjectList;
var i: integer; begin result := TSubmissionObjectList.Create; for i := 0 to Input.Count - 1 do begin if odd(i) then begin result.Add(Input.Items[i]); end; end; end; procedure TForm1.FormCreate(Sender: TObject); var x, y: TSubmissionObjectList; sub: TSubmission; i: integer; begin x := TSubmissionObjectList.Create; try for i := 0 to 100 do begin sub := TSubmission.Create; sub.MD5 := 'Test'+IntToStr(i); x.Add(sub); end; // Ist dieser Abschnitt auskommentiert, keine AV bei x.Free; y := MachWas(x); try finally y.Free; end; finally x.Free; // AccessViolation durch y.Free! end; end;
Delphi-Quellcode:
Ich befürchte, das hat wieder was damit zu tun, da Objekte nur referenziert und nicht kopiert werden. Ich weiß irgendwie nicht mehr weiter :(
type
TSubmission = class(TObject) Tags: string; Rating: string; Score: integer; PictureNumber: integer; MD5: string; end; TSubmissionObjectList = class(TObjectList) protected function getItem(Index: Integer): TSubmission; virtual; procedure setItem(Index: Integer; Objekt: TSubmission); virtual; public function Add(Objekt: TSubmission): Integer; virtual; function Remove(Objekt: TSubmission): Integer; virtual; function IndexOf(Objekt: TSubmission): Integer; virtual; procedure Insert(Index: Integer; Objekt: TSubmission); virtual; function First: TSubmission; virtual; function Last: TSubmission; virtual; property Items[index: Integer]: TSubmission read getItem write setItem; default; end; function TSubmissionObjectList.getItem(Index: Integer): TSubmission; begin Result := TSubmission(inherited Items[Index]); end; procedure TSubmissionObjectList.setItem(Index: Integer; Objekt: TSubmission); begin inherited Items[Index] := Objekt; end; function TSubmissionObjectList.Add(Objekt: TSubmission): Integer; begin Result := inherited Add(Objekt); end; function TSubmissionObjectList.First: TSubmission; begin Result := TSubmission(inherited First()); end; function TSubmissionObjectList.IndexOf(Objekt: TSubmission): Integer; begin Result := inherited IndexOf(Objekt); end; procedure TSubmissionObjectList.Insert(Index: Integer; Objekt: TSubmission); begin inherited Insert(Index, Objekt); end; function TSubmissionObjectList.Last: TSubmission; begin Result := TSubmission(inherited Last()); end; function TSubmissionObjectList.Remove(Objekt: TSubmission): Integer; begin Result := inherited Remove(Objekt); end; Gruß blackdrake |
Re: Objekt in Array kopieren und anschließend freigeben
Deine Vermutung ist richtig. Dadurch, dass Du die Objekte (besser gesagt, deren Referenzen) in die 2. Liste packst und diese dann freigibst, zeigen die entsprechenden Objektreferenzen der 1. Liste dann ins Leere.
|
Re: Objekt in Array kopieren und anschließend freigeben
Hallo.
Und was macht man dagegen? Ich kann weder auf y.Free, noch auf x.Free verzichten, da ich sonst MemoryLeaks habe. Vielleicht könnte man TSubmissionObjectList.Add() frisieren, sodass es die Objekte vorher dupliziert und dann das Duplikat hinzufügt? Die resultierende Liste y sollte eigentlich von Liste x unabhängig abhängig sein. Wie mache ich das am geschicktesten? Gruß blackdrake |
Re: Objekt in Array kopieren und anschließend freigeben
Du könntest in der Liste, die MachWas zurückgibt, OwnsObjects auf False setzen. Dann wird es allerdings wieder problematisch, falls du y neue Objekte hinzufügst.
Am besten ist wohl, TSubmission von TPersistent abzuleiten und Assign zu überschreiben. In MachWas könntest du dann die Objekte klonen. Mir fällt gerade noch eine weitere Lösung ein: Du könntest auch ein ISubmission-Interface deklarieren und die Submissions in einer TInterfaceList speichern. Die automatische Referenzzählung würde dich dann von der Pflicht befreien, die Submissions manuell freizugeben. |
Re: Objekt in Array kopieren und anschließend freigeben
Hallo.
Ich würde es vorziehen, die TSubmissionObjectList zu modifizieren, sodass sie neue Objekte dupliziert und man somit eine unabhängige Liste erzeugen kann. Dann müsste ich mich nur 1 Mal direkt in der TSubmissionObjectList um diese Angelegenheit kümmern, anstelle jede Funktion umzuschreiben, die mit TSubmissionObjectList arbeiten. Ist doch korrekt so, oder? Ich habe jetzt folgendermaßen geändert:
Delphi-Quellcode:
Fehlermeldung: 'TSubmission kann nicht zu TSubmission zugewiesen werden'.
type
TSubmission = class(TPersistent) public Tags: string; Rating: string; Score: integer; PictureNumber: integer; MD5: string; procedure Assign(Source: TPersistent); override; end; procedure TSubmission.Assign(Source: TPersistent); begin inherited; // Was soll ich hier machen? end; function TSubmissionObjectList.Add(Objekt: TSubmission): Integer; var Duplikat: TSubmission; begin Duplikat:= TSubmission.Create; Duplikat.Assign(Objekt); Result := inherited Add(Duplikat); end; Du schriebst, dass ich Assign() überschreiben müsste. Was muss ich denn genau am Code ändern, sodass Assign an mein TSubmission angepasst wird? Der Sourcecode von TPersistent.Assign() hat mir irgendwie nicht die geistige Erleuchtung gebracht. :coder2: -- Zu deinem Nachtrag: Ich werde das mit dem Interface gleich mal in einem zweiten Testprojekt ausprobieren. Gruß blackdrake |
Re: Objekt in Array kopieren und anschließend freigeben
Zitat:
|
Re: Objekt in Array kopieren und anschließend freigeben
Die klassische Implementation von Assign sieht so aus:
Delphi-Quellcode:
Du musst also einfach die Felder von Hand kopieren. Lediglich bei Feldern, die selbst Objekte beinhalten, solltest du überlegen, ob du nicht wiederum Assign verwendest, falls die Klasse es implementiert.
procedure TMeinObjekt.Assign(Source: TPersistent);
begin if Source is TMeinObjekt then begin Feld1 := TMeinObjekt(Source).Feld1; Feld2 := TMeinObjekt(Source).Feld2; Feld3 := TMeinObjekt(Source).Feld3; Feld4 := TMeinObjekt(Source).Feld4; end else inherited; end; Bezüglich Interfaces: Dann musst du Properties mit Get- und Set-Methoden verwenden. Das ist allerdings etwas Schreibarbeit. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:43 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