Autor Beitrag
Flamefire Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Do 11.09.08 22:26 
nja bin z.zt. n bissl gestresst...sry wenn ich überreagiert habe...
Hab mal drüber nachgedacht:

ausblenden volle Höhe 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:
29:
30:
31:
type
  POrdner=^TOrdner;
  TOrdner = class(TObject)
    name: String;
    Ordner: TObjectList; // Mit TOrdnern drin
    Dateien: TStringlist; // bequemer als Array of String, im Prinzip aber dasselbe ;-)
    back: POrdner;

    public
      constructor Create(sname:String='';last:POrdner=nil);
      destructor Destroy; override;
  end;
...
destructor TOrdner.Destroy;
var i:Integer;
begin
  Ordner.Free;
  Dateien.Free;
  name:='';
  inherited Destroy;
end;

constructor TOrdner.Create(sname:String='';last:POrdner=nil);
begin
  inherited Create;
  name:=sname;
  Dateien:=TStringList.Create;
  Ordner:=TObjectlist.Create;
  back:=last;
  if(last<>nil) then last^.Ordner.Add(self);
end;


So weit OK?

Wenn Ich richtig liege wird bei "Ordner.Free;" für alle Ordner in der Liste "Free" aufgerufen und damit ist das schon rekursiv. Richtig?
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 11.09.08 22:39 
Moin!

user profile iconFlamefire hat folgendes geschrieben:
Hab mal drüber nachgedacht:
Na also, geht doch. ;)

Ich würde es aber trotzdem so ansetzen:
ausblenden volle Höhe 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:
29:
30:
31:
32:
33:
34:
35:
type
  TOrdner = class(TObject)
  private
    FOwner: TOrdner;
    FName: String;
    FOrdner: TObjectList;
    FDateien: TStringList;
  public
    constructor Create(const AName: String = ''; AOwner: TOrdner = NIL);
    destructor Destroy; override;
    property Owner: TOrdner read FOwner;
    property Name: String read FName write FName;
    property Ordner: TObjectList read FOrdner;
    property Dateien: TStringList read FDateien;
  end;

implementation

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;
Um einen solchen Baum freizugeben reicht es dann, den ersten Root-Ordner mit .Free freizugeben. Allerdings ist zu beachten, dass beim Löschen von einzelnen Unterordnern über eine (externe) Objekt-Referenz trotzdem ein Eintrag in der FOrdner-Objectlist des Owners verbleibt. Deshalb also besser immer über die Methoden der enthaltenden TObjectList löschen (.Delete oder .Remove). :idea:

user profile iconFlamefire hat folgendes geschrieben:
Wenn Ich richtig liege wird bei "Ordner.Free;" für alle Ordner in der Liste "Free" aufgerufen und damit ist das schon rekursiv. Richtig?
Exakt, darauf läuft es hinaus. :)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Flamefire Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Do 11.09.08 22:59 
Ok sehr schön sauber so =)

user profile iconNarses hat folgendes geschrieben:

Allerdings ist zu beachten, dass beim Löschen von einzelnen Unterordnern über eine (externe) Objekt-Referenz trotzdem ein Eintrag in der FOrdner-Objectlist des Owners verbleibt. Deshalb also besser immer über die Methoden der enthaltenden TObjectList löschen (.Delete oder .Remove). :idea:


Du meinst damit statt: UnterOrdner.Free;
besser:
ausblenden Delphi-Quelltext
1:
UnterOrdner.Owner.Ordner[i].Free;					


Würde da das hier gehen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
destructor TOrdner.Destroy;
var tmp:TOrdner;
begin
  tmp:=FOwner;
  if(tmp<>nil) then begin
    FOwner:=nil;
    tmp.Ordner.Remove(self)
  end else begin
    FreeAndNil(FDateien);
    FreeAndNil(FOrdner);
    inherited;
  end;
end;

Oder führt das möglichweise zur Zugriffsverletzung?

EDIT: Getestet: Logischerweise Zugriffsverletzung...Gibt es ne andre Möglichkeit? Sowas wie dass er die Zeile "tmp.Ordner.Remove(self)" in ne art warteliste stellt und ausführt, sobald er aus Destroy zurückkehrt?
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 11.09.08 23:11 
Moin!

user profile iconFlamefire hat folgendes geschrieben:
Du meinst damit statt: UnterOrdner.Free;
besser:
ausblenden Delphi-Quelltext
1:
UnterOrdner.Owner.Ordner[i].Free;					
Nein, so:
ausblenden Delphi-Quelltext
1:
2:
UnterOrdner.Owner.Ordner.Extract(Unterordner);
UnterOrdner.Free;
oder gleich:
ausblenden Delphi-Quelltext
1:
UnterOrdner.Owner.Ordner.Remove(Unterordner);					
Wobei hier sicherzustellen ist, dass Owner auch nicht NIL ist!

user profile iconFlamefire hat folgendes geschrieben:
Würde da das hier gehen:
Nein, das inherited Destroy; muss auf jeden Fall ausgeführt werden. Du könntest höchstens mit einem if Assigned(FOwner) als erste Anweisung auf einen solchen reagieren und dich dann dort austragen lassen (macht die VCL bei den Components auch so). Allerdings musst du dann die beiden Fälle unterscheiden: a) einzelnes Objekt "ausnahmsweise" freigeben und b) einen Objektbaum abhacken (z.B. mit .Destroying: Boolean oder so machbar). Ich würde das aber lassen und ggfs. manuell die Referenz entfernen. ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Flamefire Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Do 11.09.08 23:31 
Perfekt. Das Extrakt ist es:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
destructor TOrdner.Destroy;
begin
  If(FOwner<>nil) then FOwner.FOrdner.Extract(self);
  FreeAndNil(FDateien);
  FreeAndNil(FOrdner);
  inherited;
end;


EDIT: Ist aber ineffizient, da die Suche und das Entfernen auch gemacht wird, wenn der ganze Baum gelöscht wird
Besser:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
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;


Kommt zwar ne Warnmeldung von Delphi aber das sollte so gehen. Oder hab ich was übersehen?