Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Gibt TObject Speicherplatz wieder frei ? (https://www.delphipraxis.net/51833-gibt-tobject-speicherplatz-wieder-frei.html)

Hansa 19. Aug 2005 21:05


Gibt TObject Speicherplatz wieder frei ?
 
Hi,

ich habe hier eine Prozedur, deren Parameterliste wird immer größer. Die habe ich jetzt umgebaut in ein TObject. Brauche 2 Methoden und die vorherigen Paramter sind nun Felder vom TObject. Die Delphi-Hilfe ist nun recht knapp und etwas irreführend. Offensichtlich muß ich die Dinger mit Create erzeugen, aber wie siehts mit der Freigabe aus ?

kiar 19. Aug 2005 21:10

Re: Gibt TObject Speicherplatz wieder frei ?
 
moin Hansa,


vllt
Delphi-Quellcode:
DieDinger.free
raik

jbg 19. Aug 2005 21:11

Re: Gibt TObject Speicherplatz wieder frei ?
 
"Wer was erzeugt, ist auch für die Freigabe verantwortlich".

Du musst das Objekte selber mit .Free wieder freigeben. Am besten macht das die Funktion bzw. das übergeordnete Objekt, das auch dein Hilfobjekt erzeugt hat.

jfheins 19. Aug 2005 21:13

Re: Gibt TObject Speicherplatz wieder frei ?
 
Delphi-Quellcode:
procedure DoSomething (Obj: TMyObj);
begin
Obj.DoSomethingElse;
Form1.Caption := Obj.Text;
end;

// ...

begin
  Obj := TMyObj.Create;
  Obj.FillWithData;
  DoSomething (Obj);
  Obj.Free;
end;
;)

Hilft dir das ?

Hansa 19. Aug 2005 21:24

Re: Gibt TObject Speicherplatz wieder frei ?
 
Mann, seid ihr flott. :mrgreen:

Aber was hat das hier zu bedeuten :

Zitat:

Zitat von DH
Rufen Sie Destroy nicht direkt auf. Verwenden Sie stattdessen Free. Die Methode Free überprüft, ob die Objekt-Referenz nicht bereits nil ist und ruft Destroy nur bei Bedarf auf.

Die in TObject definierte Version von Destroy gibt den Speicher frei. Abgeleitete Objekte definieren normalerweise einen eigenen Destruktor.

Wenn Sie eine Methode Destroy in einem abgeleiteten Objekt deklarieren, beachten Sie folgendes: Fügen Sie in die Deklaration immer die Direktive override ein, und rufen Sie als letzte Anweisung in der überschriebenen Methode die geerbte Version von Destroy auf. Da Destroy eine virtuelle Methode ist, stellen Sie durch Überschreiben der Methode sicher, dass das gewünschte Verhalten auftritt.

Hinweis: Wenn ein Konstruktor eine Exception nicht behandelt, wird der Destruktor aufgerufen, der die unvollständig initialisierte Objektinstanz wieder freigibt. Deshalb sollten Destruktoren vor der Freigabe überprüfen, ob die zugewiesenen Ressourcen, wie z.B. Handles, tatsächlich zugewiesen wurden (deren Wert könnte Null sein).

Die Methode Destroy sollte so implementiert werden, dass sie Free für Unterobjekte aufruft, die durch den Objektkonstruktor erzeugt (zugewiesen) wurden. Im Gegensatz zu Destroy besitzt Free einen Sicherheitsmechanismus für die Freigabe von Objekten, die nil sind.

An anderer Stelle steht auch noch, man solle Create nicht explizit aufrufen. :shock: Habe jetzt noch in funktionierendem Programm nachgesehen, wie ich es da gemacht habe. Und zwar mit Destroy und nachfolgendem := NIL. Weiß jetzt nicht mehr genau warum, aber daran war Borland höchstpersönlich beteiligt !

jfheins 19. Aug 2005 21:28

Re: Gibt TObject Speicherplatz wieder frei ?
 
also Create nicht direkt aufrufen :shock:
Ich glaube, das Risiko kannst du eingehen ;)

.Destroy gibt den Speicher frei,

.Free:
Delphi-Quellcode:
if xyz <> nil then
  yxz.Destroy
freeAndNil:
Delphi-Quellcode:
xyz.free;
xyz := nil;
(in etwa ;))

Dax 20. Aug 2005 00:16

Re: Gibt TObject Speicherplatz wieder frei ?
 
Den Konstruktor aufrufen bedeutet
Delphi-Quellcode:
obj := TObject.Create;
Den Konstruktor explizit aufrufen wäre
Delphi-Quellcode:
obj.Create
;)

Hansa 20. Aug 2005 00:30

Re: Gibt TObject Speicherplatz wieder frei ?
 
Habe die erste Variante verwendet. Aber, wie gesagt, es geht um das danach, also das freigeben.

Dani 20. Aug 2005 01:12

Re: Gibt TObject Speicherplatz wieder frei ?
 
:shock: Wie kann man 5000 Beiträge in einem Delphi-Forum sammeln ohne...schon gut. Resourcenschutzblock nicht vergessen. :warn:

Delphi-Quellcode:
procedure foo;
var Inst: TMyObject;
begin
  //Instanz erzeugen
  Inst := TMyObject.Create;
  try
   //Etwas machen, das eine Exception auslösen kann
   Inst.DoSomething;
  finally
   //Sicherstellen, dass das Objekt freigegeben wird
   Inst.Free;
  end;
 //Ab hier nicht mehr auf Inst zugreifen, sonst AV
end;
Wenn das Objekt im Constructor Instanzen von anderen Klassen erzeugt, müssen die unbedingt im Destructor wieder freigegeben werden.

Delphi-Quellcode:
type
  TMyObject = class(TObject)
  private
   FStrings: TStrings;
   procedure SetStrings(Value: TStrings);
  public
   constructor Create;
   destructor Destroy; override;
  published
   property Strings: TStrings read FStrings write SetStrings;
  end;

implementation
 
constructor TMyObject.Create;
begin
 inherited;
 FStrings := TStringlist.Create;
end;

destructor TMyObject.Destroy;
begin
 FStrings.Free;
 inherited;
end;

procedure TMyObject.SetStrings(Value: TStrings);
begin
 If Assigned(Value) then FStrings.Assign(Value);
end;
edit: fehler im code beseitigt

Hansa 20. Aug 2005 01:28

Re: Gibt TObject Speicherplatz wieder frei ?
 
Zitat:

Zitat von Dani
:shock: Wie kann man 5000 Beiträge in einem Delphi-Forum sammeln

Meinst Du damit mich oder vielleicht eher Luckie ? :lol: Was soll das finally denn da nützen ? Also gut : Du verwendest Destroy und Constructor/Destructor. Wie ich das sehe wird das free in ein Destroy umgebogen und das NIL bleibt außer acht. Was nun ?

Luckie 20. Aug 2005 01:59

Re: Gibt TObject Speicherplatz wieder frei ?
 
Sag mal Hansa, was ist den nmit dir los? Du programmierst doch schon eine ganze Weile und jetzt solche Fragen? :shock:

Also, Destroy sollte man nie direkt aufrufen, sondern nur über die Methode Free, da Free vorher prüft, ob das Objekt nicht nil ist. Erzeugst du in deiner Klasse weitere Instanzen, überschreibst du Destroy in deiner Klasse, gibst aber die Instanz der Klasse selber mit Free frei.

Delphi-Quellcode:
type
  TExample = class(TObject)
    private
      sl: TStringList;
    public
      Constructor Create;
      Destructor Destroy; override;
  end;

Constructor TExample.Create;
begin
  inherited;
  sl := TStringList.Create;
end;

Destructor TExample.Destroy;
begin
  ShowMessage('Kuckuck');
  sl.Free;
  inherited Destroy;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  MyExample: TExample;
begin
  MyExample := TExample.Create;
  try
  finally
    MyExample.Free;
  end;
end;
So. Free wirft die Instanze aus dem Speicher, aber der Zeiger wird nicht auf nil gesetzt. So das nach dem Free ein Test auf nil immer noch True ergibt. Entweder man setzt den Zeiger nun von Hand auf nil oder man läßt es die VCL machen und nutzt die Prozedur FreeAndNil.

Ich verstehe jetzt aber nicht so ganz dein Problem, denn das kann es ja nicht gewesen sein, denn das hast du ja hoffentlich schon drauf, ansonsten wüßte ich nicht, wie du bisher mit deinen Programmen Geld verdient hast. :gruebel:

Hansa 23. Aug 2005 18:08

Re: Gibt TObject Speicherplatz wieder frei ?
 
Das Thema interessiert wirklich nur am Rande. 8) Ich will die Parameter in der Prozedur ersetzen. Reicht da nicht ein bloßes free ? Es geht um keine komplexen Strukturen ! Ich will z.B. so was :

Delphi-Quellcode:
procedure SchreibeDatei (ID_KUNDE,
                         ID_ART,
                         Ges integer;
                         EKpreis,
                         VKpreis : real;
                         gratis,
                         zurueck : boolean);
ersetzen mit TObject-Feldern. Das ist auf Dauer übersichtlicher. 8)

Luckie 23. Aug 2005 18:10

Re: Gibt TObject Speicherplatz wieder frei ?
 
Die Felder vom Typ TObejct müssen ja irgendwo erzeuugt werden und wen ndu keine Speicherlecks produzieren willst, musst du sie auch wieder freigeben. Psote doch mal Code, wie du dir das konkret vorstellst.

Hansa 23. Aug 2005 18:22

Re: Gibt TObject Speicherplatz wieder frei ?
 
Wie gesagt, ich will lediglich von der ellenlangen Prozedur-Parameterliste weg ! Hier ist das (stark reduzierte) TObject :

Delphi-Quellcode:
TStatSpeichern = class(TObject)
  monat,
  jahr,
  menge : smallint;
...
  public
    procedure SchreibeStat (KuNr : integer);
end;
Hier ist die Prozedur :

Delphi-Quellcode:
procedure TStatSpeichern.SchreibeStat (KuNr : integer);
begin
  with EingDM.StatSP do begin
    ParamByName ('MONAT').AsInteger := monat;
    ParamByName ('JAHR').AsInteger := jahr;
    ParamByName ('MENGE').AsInteger := Menge;
...
    ExecProc;
  end;
end;
Das ist zwar jetzt eine SQL Stored Procedure tut aber nichts zur Sache. Allerdings bin ich gerade am überlegen, ob ein Create nicht etwa sogar überflüssig ist. :gruebel:

Luckie 23. Aug 2005 18:25

Re: Gibt TObject Speicherplatz wieder frei ?
 
Das ist nichts weiter als eine Klasse mit TObject als Vorfahre. Und um sie benutzen zu können, wirst du eine Instanz erstellen müssen und die musst du wieder aus dem Speicher entfernen. Wie, das haben wir dir schon erklärt.

Hansa 24. Aug 2005 00:38

Re: Gibt TObject Speicherplatz wieder frei ?
 
Es sieht so aus, daß sogar der Vorfahre überflüssig ist ! Also OOP pur. 8)

dizzy 24. Aug 2005 01:36

Re: Gibt TObject Speicherplatz wieder frei ?
 
TObject ist immer (erster) Vorfahre. Ob du es nun explizit angibst oder nicht ist völlig unerheblich. (Hatten wir das nicht auch schon mal vor einiger Zeit diskutiert? 8))

Luckie 24. Aug 2005 01:41

Re: Gibt TObject Speicherplatz wieder frei ?
 
Jupp, war, glaube ich, irgendwie im Zusammenhang mit meinem Klassen-Tutorial oder so.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:34 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