AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Objekte freigeben

Ein Thema von SteffenSchm · begonnen am 25. Feb 2009 · letzter Beitrag vom 3. Mär 2009
Antwort Antwort
Seite 2 von 3     12 3      
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#11

Re: Objekte freigeben

  Alt 25. Feb 2009, 18:36
Zitat von mjustin:

wirft eine 'Externe Exception C00001D' (in D6, und etwas ähnliches in D2009).

Warnungen oder Hinweise wegen der nicht initialisierten Variable X gibt es keine - da muss man halt aufpassen
Bei lokalen Variablen ist das auch klar. Das tritt aber nur bei lokalen Variablen auf. Und da passt man sowieso auf. bzw. hat die entsprechende Methode im Überblick.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.142 Beiträge
 
Delphi 12 Athens
 
#12

Re: Objekte freigeben

  Alt 25. Feb 2009, 18:46
Variablen sollte man eh immer Initialisieren. (bevor man lesend drauf zugreifen könnte)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#13

Re: Objekte freigeben

  Alt 25. Feb 2009, 19:49
Diejenige Klasse, die eine oder mehrere Objekte erzeugt, sollte normalerweise auch die Verantwortung für die Freigabe übernehmen.
Eine Klasse, die in ihrem Konstruktor Unterobjektte erzeugt sollte dann die Verantwortung für ihre Freigabe im Destruktor übernehmen.

Die Anwendung von FreeAndNil() ist häufig ein Kennzeichen dafür, dass die Verantwortlichkeiten nicht sauber geregelt sind.
Delphi-Quellcode:
TMyBox = class(TWorldBox)
  public
    { Public-Deklarationen }
    Parameter : TParmeter;
    destructor Destroy; override;
   end;

destructor TMyBox.Destroy;
begin
  FreeAndNil(Parameter); // Falsch!
  // die Variable Parameter wurde ganz offensichtlich von einer anderen Klasse erstellt
  // TMyBox trägt nicht die Verantwortung für die Freigabe
  // FreeAndNil() wäre sowieso sinnlos, da die Variable Parameter demnächst "out of scope" geht

  inherited Destroy;
end;
Also nicht blind mit FreeAndNil() um sich schiessen, sondern genau überlegen.
  Mit Zitat antworten Zitat
SteffenSchm

Registriert seit: 2. Nov 2004
Ort: Herzogenaurach
84 Beiträge
 
Delphi 10.3 Rio
 
#14

Re: Objekte freigeben

  Alt 26. Feb 2009, 09:35
Vielen Dank für die vielen Hinweise und die interessante Diskussion. Noch ein paar Erläuterungen:

Die Klasse TMyBox stellt Daten in Abhängigkeit von Parametern da. Das Objekt Parameter wird in dieser Klasse im constructor erzeugt und auch im destructor wieder freigegeben. (@sx2008as FreeAndNil an dieser Stelle ist tatsächlich nutzlos. Ich habe es deshalb wieder zurückgenommen.) Die Klasse sieht jetzt so aus:

Delphi-Quellcode:
TMyBox = class(TWorldBox)
  public
    { Public-Deklarationen } 
    Parameter : TParmeter;
    construcor Create(AOwner: TComponent); override;
    destructor Destroy; override;
   end;

constructor TMyBox.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Parameter :=TParameter.Create;
end;

destructor TMyBox.Destroy;
begin
  Parameter.Free;
  inherited Destroy;
end;
Diese Klasse nutze ich für verschiedene Projekte. Ich will sie deshalb für das aktuelle Problem nichr grundlegend ändern. Im aktuellen Projekt soll es aber möglich sein, zwischen drei unterschiedlichen Darstellungen umzuschalten. Die Art der drei Darstellungen ist in drei Objekten TParameter gespeichert. Den aktuell zu verwendenden weise ich dann MyBox.Parameter zu. Das grundlegende Problem war, dass ich nach Freigabe von MyBox nicht wusste, welcher der drei Parameterobjekte bereits freigegeben ist.

Ich habe mich jetzt dazu entschlossen das aufrufende Objekt von TMyBox abzuleiten. Das ganze sieht jetzt so aus:

Delphi-Quellcode:
  TArea = class(TMyBox)
  public
    ParameterA,
    ParameterB,
    ParameterC: TParameter;
    construcor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

constructor TArea.Create(AOwner: TComponent);
begin
  inherited Create(MainForm);
  Parent := MainForm.TabControl;
 
  ParameterA := Parameter;
  ParameterB := TParameter.Create;
  Parameterc := TParameter.Create;
 end;

destructor TCalcArea.Destroy;
begin
  FreeAndNil(ParameterA);
  FreeAndNil(ParameterB);
  FreeAndNil(ParameterC);
  Parameter:=Nil;
  inherited Destroy;
end;
Ich habe damit immer drei erzeugte TParameter-Objekte aber vier Zeiger die darauf zeigen. Im destructor von TArea gebe ich aller drei erzeugten Parameter frei. Den vierten Zeiger muss ich aber zusätzlich auf Nil setzen, ansonsten würde Parameter.Free im destructor von TMyBox zum Fehler führen.

Das ganze scheint jetzt so zu funktionieren. Für Hinweise und Anregungen bin ich dennoch dankbar !
Steffen
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#15

Re: Objekte freigeben

  Alt 26. Feb 2009, 17:49
Diese Deklaration ist nicht sicher:
Delphi-Quellcode:
TMyBox = class(TWorldBox)
 public
   { Public-Deklarationen } 
   Parameter : TParameter;
   construcor Create(AOwner: TComponent); override;
   destructor Destroy; override;
end;
Das Problem ist, dass jeder von Aussen die Variable Parameter umbiegen kann.
Das führt zwangsläufig zu Fehlern.

Über ein Property kann man die Sache aber wasserdicht machen:
Delphi-Quellcode:
TMyBox = class(TWorldBox)
 private
   FParameter : TParameter;
   procedure SetParameter(value:TParameter);

 public
   { Public-Deklarationen } 
   construcor Create(AOwner: TComponent); override;
   destructor Destroy; override;
   property Parameter : TParameter read FParameter write SetParameter;
end;

procedure TMyBox.SetParameter(value:TParameter);
begin
  FParameter.Assign(value);
end;
Die Klasse TParameter muss von TPersistent abgeleitet werden und die Methode Assign muss überschrieben werden.
Mehr zu Assign() - leider auf englisch http://delphi.about.com/od/course/a/delphi_oop21.htm
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#16

Re: Objekte freigeben

  Alt 26. Feb 2009, 19:57
Anstatt Assign besser AssignTo überschreiben. aber vielleicht braucht er ja keinen Setter. Der gezeigte Code oben ist "schlecht", aber für Verbesserungen braucht man hier mehr Informationen.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
SteffenSchm

Registriert seit: 2. Nov 2004
Ort: Herzogenaurach
84 Beiträge
 
Delphi 10.3 Rio
 
#17

Re: Objekte freigeben

  Alt 27. Feb 2009, 07:27
Danke für die Hinweise.

Wenn ich das richtig verstehe, wird mit Assign (oder AssignTo) dann der Inhalt des Objektes auf ein neues Objekt kopiert. Ich brauche dann tatsächlich vier erzeugte und auch wieder freizugebende Objekte vom Typ TParameter. Dann ist das mit dem Freigeben natürlich klar geregelt und erzeugt keine Konflikte.

Ich hatte versucht, nur einen Zeiger auf das aktuelle Objekt Parameter zu setzen (bzw. umzubiegen). Ich dachte das wäre effizienter. Aber es ist wohl nicht ganz sauber programmiert.

Noch eine Frage: Wenn ich den Parameter in MyBox über ein property anspreche, warum kann ich dann nicht in der Methode SetParameter den Code reinschreiben, den ich in die Methode Assign bzw. AssignTo der von TPersistent abgeleiteten Klasse TParameter schreiben soll. Wäre zumindest für mich dann einfacher zu lesen und zu verstehen.
Steffen
  Mit Zitat antworten Zitat
SteffenSchm

Registriert seit: 2. Nov 2004
Ort: Herzogenaurach
84 Beiträge
 
Delphi 10.3 Rio
 
#18

Re: Objekte freigeben

  Alt 27. Feb 2009, 16:17
Das ganze wirft bei mir jetzt eine prinzipielle Frage auf.

Ich "missbrauche" Ableitungen von TObject auch an anderen Stellen noch als Zeiger. Am besten vielleicht an einem Beispiel zu erklären:

Ich habe eine Datenstruktur ähnlich einer Master/Detail-Tabelle in einer Datenbank. Die Mastertabelle (bzw. -liste) ist eine Objektliste mit z.B. Werkstücken. Sie enthält Verweise auf eine Detailtabelle (auch hier wieder eine Objektliste) in der der Werkstoff des Werkstücks steht.

Für die Werkstoffe habe ich ein Objekt vom Typ TMat = class(TObject) definiert. Diese Objekte werden erzeugt, in der Liste gespeichert und am Ende auch wieder freigegeben.

Innerhalb des Objektes Werkstück benutze ich auch TMat, hier aber nur als Zeiger auf ein Element der Materialliste. Es wird vom Objekt Werkstück weder erzeugt noch freigegeben.

Ist das aus OOP-Gesichtspunkten so o.k., oder sollte man das prinzipiell anders machen.

Vielleicht schaut jemand mit Ahnung noch mal in dieses Thema rein und hat eine Anmerkung bzw. einen Hinweis. Besten Dank!
Steffen
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#19

Re: Objekte freigeben

  Alt 28. Feb 2009, 10:35
Zitat von SteffenSchm:
Noch eine Frage: Wenn ich den Parameter in MyBox über ein property anspreche, warum kann ich dann nicht in der Methode SetParameter den Code reinschreiben, den ich in die Methode Assign bzw. AssignTo der von TPersistent abgeleiteten Klasse TParameter schreiben soll. Wäre zumindest für mich dann einfacher zu lesen und zu verstehen.
Es ist besser, eine Klasse die Möglichkeit zu geben, Objekte zu kopieren, als dass man diese Aufgabe in sehr begrenzter Form einer anderen Klasse überlässt.
Die Klasse TParameter weiss selbst am Besten, wie sich sich kopieren soll.

Assign() oder AssignTo():
Wenn eine Klasse Objekte von sich selbst kopieren soll, dann verwendet man immer Assign().
AssignTo() kommt nur in ganz bestimmten Sonderfällen zum Einsatz.
Angenommen, man hat eine neue Klasse namens TSuperBitmap geschrieben.
Dann möchte man sicher die SuperBitmap auch auf ein normales TBitmap-Objekt kopieren:
bitmap.Assign(superbitmap); Jetzt ergibt sich nur das Problem, dass die Klasse TBitmap unsere neue Klasse TSuperbitmap nicht kennt.
Und man kommt auch an TBitmap.Assign() nicht heran, weil der Code in der VCL steckt.
Aber man kann die Sache umdrehen und TSuperBitmap.AssignTo() überschreiben und so das Dilemma lösen.
  Mit Zitat antworten Zitat
schöni

Registriert seit: 23. Jan 2005
Ort: Dresden
445 Beiträge
 
Delphi 7 Personal
 
#20

Re: Objekte freigeben

  Alt 28. Feb 2009, 11:32
Hallo,

Keine Ahnung, ob es im konkreten Fall hilft, aber ich gebe Objekte grundsätzlich nach Stack-Prinzip frei. In umgekehrter Reihenfolge der Initialisierung:

Delphi-Quellcode:
var
 Object1: TMyFirstClass;
 Object2: TMySecondClass;
 Object3: TMyThirdClass;

begin
  Object1 := TMyFirstClass.Create;
  Object2 := TMySecondClass.Create;
  Object3 := TMyThierClass.Create;
  ...
  if Assigned(Object3) then FreeAndNil(Object3);
  if Assigned(Object2) then FreeAndNil(Object2);
  if Assigned(Object1) then FreeAndNil(Object1);
end.
Damit der Topf nicht explodiert, lässt man es ab und zu mal zischen.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:02 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz