Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Destruktor überladen (https://www.delphipraxis.net/47712-destruktor-ueberladen.html)

Majortomster 15. Jun 2005 09:22


Destruktor überladen
 
Hallo,

ich habe in meiner Klasse den Destruktor überladen, um darin Speicher wieder freizugeben(mit free), der in den Instanzen benutzt wird.
Jetzt ist mir folgendes aufgefallen:
Wenn ich eine Instanz dieser Klasse mit .Free() freigebe, dann scheint dieser Destruktor gar nicht aufgerufen zu werden - obwohl es heißt, dass Free() nachschaut ob das Objekt nil ist und wenn nicht dann den Destruktor aufruft.

Daraufhin dachte ich mir, ich muss dann auch free() überladen, um dort auf den Destruktor zu verweisen.
Ich tat dies, nach einer Prüfung, ob self <> nil ist.

Dadurch wird der Destruktor zwar aufgerufen, aber es zeigt sich der seltsame Effekt, dass eine Exception geworfen wird wenn ich zwei Mal in Folge auf das gleiche Objekt Free() anwende.

Weiß einer wie man das handhaben kann?

Gruß, T

Bernhard Geyer 15. Jun 2005 09:26

Re: Destruktor überladen
 
Zeig mal etwas Code. Wurde der Destructor auch mit override angegeben?

phlux 15. Jun 2005 09:27

Re: Destruktor überladen
 
Code?? :stupid:
Edit: Der Geyer war schneller :zwinker:

Majortomster 15. Jun 2005 09:34

Re: Destruktor überladen
 
Klar ihr habt Recht - ein bisschen Code sagt mehr als mein halber Roman ;)

Delphi-Quellcode:
public destructor Destroy(); reintroduce; overload;
public procedure Free(); overload;
...
Delphi-Quellcode:
destructor TsqlReplace.Destroy();
begin
   ds.Free;
   fieldStrs.Free;
   datenbank := '';
   tabelle := '';
   bedingung := '';
   queryExecuted := false;
   inherited;
end;

procedure TsqlReplace.Free();
begin
   if(self <> nil) then
      Destroy();
end;

phlux 15. Jun 2005 09:36

Re: Destruktor überladen
 
Hi!
1. Reintroduce() weg
2. ersetze Overload durch override
3. Die Methode Free musst du dann nicht mehr überschreiben (ausserdem fehlt dort ein inherited)

mfg

Stevie 15. Jun 2005 09:38

Re: Destruktor überladen
 
Wahhh, Pornographie!!! (Zitat meines Ex-Informatik-Lehrers) :mrgreen:

Wenn du Blubb.Free aufrufst, ist das Objekt freigegeben, also Blubb = nil
und ein nochmaliger Zugriff auf dieses Object erzeugt eine Zugriffsverletzung,
weil es ja nunmal nicht mehr existiert.

Die Frage ist außerdem, warum hast du deinen destructor überladen???
Gibt es die Notwendigkeit, verschiedene Versionen davon zu haben?
Normalerweise reicht es, ihn zu überschreiben, falls intern benutzte
Objekt-Instanzen freigegeben werden müssen.

P.S. Phlux hat die Lösung parat ;-)

Sharky 15. Jun 2005 09:42

Re: Destruktor überladen
 
Zitat:

Zitat von Stevie
... Wenn du Blubb.Free aufrufst, ist das Objekt freigegeben, also Blubb = nil

Hai Stevie,

bist Du sicher das durch Blubb.Free Blubb auch "nil wird"? ;-)

BTW: Warum immer "blubb" ? :stupid:

Majortomster 15. Jun 2005 09:45

Re: Destruktor überladen
 
Danke schonmal für die Antwort - teste es gerade.

Zu Stevies Aussage:
Meiner Beobachtung zufolge wird durch Blubb.Free() die Referenz NICHT zu nil.
Daher endete ein wiederholter Aufruf von Free() in meinen Tests immer in einer Exception...

T

Bernhard Geyer 15. Jun 2005 09:51

Re: Destruktor überladen
 
Zitat:

Zitat von Majortomster
Meiner Beobachtung zufolge wird durch Blubb.Free() die Referenz NICHT zu nil.
Daher endete ein wiederholter Aufruf von Free() in meinen Tests immer in einer Exception...

Dafür gibt in neuen Delphi-Versionen ja FreeAndNil!

Stevie 15. Jun 2005 10:04

Re: Destruktor überladen
 
Zitat:

Zitat von Sharky
bist Du sicher das durch Blubb.Free Blubb auch "nil wird"? ;-)

BTW: Warum immer "blubb" ? :stupid:

Nein, natürlich nicht, hab mich falsch ausgedrückt... :oops:
Ich wollte damit sagen, dass die Objekt-Instanz freigegeben wird,
und nicht mehr gültig ist, der Zeiger kann nach wie vor auf den
Speicherbereich zeigen, wo sich das Objekt befand.

Findest du Blubb nicht gut? ... Ist doch inzwischen sowas wie Foo, oder nicht? ;-)

Zitat:

Zitat von Majortomster
Zu Stevies Aussage:
Meiner Beobachtung zufolge wird durch Blubb.Free() die Referenz NICHT zu nil.
Daher endete ein wiederholter Aufruf von Free() in meinen Tests immer in einer Exception...

Stimmt, aber der Aufruf des ererbten destructors führt dann ins nirvana.

Majortomster 15. Jun 2005 10:33

Re: Destruktor überladen
 
Aber der Aufruf des überschriebenen Destruktors führt ins Chaos (da dort auch Free für klasseninterne Komponenten eingesetzt wird).

phlux 15. Jun 2005 10:38

Re: Destruktor überladen
 
Eigentlich logisch das alles was das zu free-ende Objekt als Parent hat mit ge-free-ed wird oder habe ich die aussage falsch aufgenommen?

Majortomster 15. Jun 2005 10:49

Re: Destruktor überladen
 
Ja das ist logisch - aber mittlerweile entgeht mir total der Sinn von Free.
Ich hatte das so verstanden, dass dies eine SICHERE Art ist, den Destruktor aufzurufen (oder eben nicht, wenn die Referenz nil ist).
Aber was ist diese Methode wert, wenn sie selbst in Bedrängnis kommt (Exception mit Speicherlesefehler), wenn sie zwei Mal in Folge aufgerufen wird..?
In einem äußerst komplexen Programm mit sehr vielen verschiedenen Objekten die viel Speicher fressen, ist man da echt aufgeschmissen... oder sehe ich das falsch?

(jedenfalls klappt es jetzt super mit FreeAndNil(objekt) - danke :-D )

T

r2c2 15. Jun 2005 10:53

Re: Destruktor überladen
 
Zitat:

Zitat von Majortomster
Ja das ist logisch - aber mittlerweile entgeht mir total der Sinn von Free.
Ich hatte das so verstanden, dass dies eine SICHERE Art ist, den Destruktor aufzurufen (oder eben nicht, wenn die Referenz nil ist).
Aber was ist diese Methode wert, wenn sie selbst in Bedrängnis kommt (Exception mit Speicherlesefehler), wenn sie zwei Mal in Folge aufgerufen wird..?
In einem äußerst komplexen Programm mit sehr vielen verschiedenen Objekten die viel Speicher fressen, ist man da echt aufgeschmissen... oder sehe ich das falsch?

(jedenfalls klappt es jetzt super mit FreeAndNil(objekt) - danke :-D )

T

Genau für solche "äußerst komplexen Programme mit sehr vielen verschiedenen Objekten die viel Speicher fressen" ist FreeAndNil gedacht. Dann kann nämlich nix mehr passieren. :zwinker:
Free kann man dann immer noch "gebrauchen", z.B. für lokale Objekte; da bringt das "nillen" nix, wenn die Procedure eh zu ende ist.

mfg

Christian

Robert_G 15. Jun 2005 10:59

Re: Destruktor überladen
 
Wenn du deinen Destructor mit overload deklarierst ist es eine ANDERE Methode als der Destructor des Vorgängers und damit wiederum ein anderer als der von TObject!!!
Free wird TObject.Destroy aufrufen. Nur wenn du es ÜBERSCHREIBST wird dann dein Code ausgeführt.
Und ja, das ist ein bequemer und sicherer Weg Speicher freizugeben. Du solltest dich einfach noch ein bisschen in OO Vorgehensweisen belesen.
Virtual methods sind IMHO eines der wichtigsten Prinzipien von objektorientierter Programmierung, das sollte man als Delphisti schon wissen. ;)

@r2c2
Habe ich früher auch oft gemacht.
Mittlerweile wirkt FreeAndNil für mich wie irgendein Artefakt, dass irgendwie nicht so richtig in den Code passt.
Wie oft hat man schon eine Referenz, die man auf nil setzen will, die kein Interface ist? :zwinker:

r2c2 15. Jun 2005 11:15

Re: Destruktor überladen
 
Zitat:

Zitat von Robert_G
@r2c2
Habe ich früher auch oft gemacht.
Mittlerweile wirkt FreeAndNil für mich wie irgendein Artefakt, dass irgendwie nicht so richtig in den Code passt.
Wie oft hat man schon eine Referenz, die man auf nil setzen will, die kein Interface ist? :zwinker:

FreeAndNil Artefakt? :gruebel:
Zugegeben ich benutze FreeAndNil kaum, aber das hängt meiner Meinung daran, dass ich noch nicht so lange OO programmiere. Bisher hab ich fast nur lokale Objekte benutzt und ansonsten eine Art "Matster-Objekt" erstellt, das alle anderen Objekte erzeugt un im Destructor wieder freigibt. Ich kann mir aber duchaus vorstellen, dass in größeren Projekten FreeAndNil sinnvoll sein kann. Oder?

mfg

Christian

Robert_G 15. Jun 2005 11:56

Re: Destruktor überladen
 
Zitat:

Zitat von r2c2
FreeAndNil Artefakt? :gruebel:
Zugegeben ich benutze FreeAndNil kaum, aber das hängt meiner Meinung daran, dass ich noch nicht so lange OO programmiere. Bisher hab ich fast nur lokale Objekte benutzt und ansonsten eine Art "Matster-Objekt" erstellt, das alle anderen Objekte erzeugt un im Destructor wieder freigibt.

Dann ist der Container ja auch weg. Warum sollte man also extra einen Zeiger auf nil setzen, wenn der einzige, der den Zeiger benutzt auch schon im Sterben liegt? ;)
Free ist eine Methode, FreeAndNil ist eine lose Funktion, vllt liegt es daran, dass es mir irgendwie komisch und fehl am Platze vorkommt. ;)

r2c2 15. Jun 2005 15:08

Re: Destruktor überladen
 
@Robert_G
Zitat:

Zitat von Robert_G
Dann ist der Container ja auch weg. Warum sollte man also extra einen Zeiger auf nil setzen, wenn der einzige, der den Zeiger benutzt auch schon im Sterben liegt? ;)

:wiejetzt: Ich glaub du hast meinen Post nicht ganz verstenden. Les ihn dir am Besten nochmal durch:

Zitat:

Zitat von r2c2
FreeAndNil Artefakt? :gruebel:
Zugegeben ich benutze FreeAndNil kaum, aber das hängt meiner Meinung daran, dass ich noch nicht so lange OO programmiere. Bisher hab ich fast nur lokale Objekte benutzt und ansonsten eine Art "Matster-Objekt" erstellt, das alle anderen Objekte erzeugt un im Destructor wieder freigibt. Ich kann mir aber duchaus vorstellen, dass in größeren Projekten FreeAndNil sinnvoll sein kann.

Letzterer Satz bedeutet:
1. Ich benutze FreeAnd Nil kaum
2. Das war in meinen beschriebenen 2 Fällen auch nicht notwendig
3. In größeren Projekten(meinend nicht in meinen bisherigen) kann dies aber IMHO sinnvoll sein

Zitat:

Zitat von Robert_G
Free ist eine Methode, FreeAndNil ist eine lose Funktion, vllt liegt es daran, dass es mir irgendwie komisch und fehl am Platze vorkommt. ;)

Ähm, keine Ahnung, du musst schon selbst wissen, warum dir was komisch vorkommt, hört sich für mich aber logisch an.

@All
Gibt es eigentlich eine sinnvolle Begründung dafür den destructor zu überladen? Warum sollte man das tun? Reicht ein Destructor nicht?

mfg

Christain

Robert_G 15. Jun 2005 15:34

Re: Destruktor überladen
 
Zitat:

Zitat von r2c2
@Robert_G :wiejetzt: Ich glaub du hast meinen Post nicht ganz verstenden. Les ihn dir am Besten nochmal durch:

Hmmm.... den habe ich wohl etwas falsch verstanden. Sehe deshalb meinen beitrag als Bestätigung für die Punkte 1 & 2. :mrgreen:
Nur denn verstehe ich nicht ganz:
Zitat:

Zitat von r2c2
3. In größeren Projekten(meinend nicht in meinen bisherigen) kann dies aber IMHO sinnvoll sein

Mir fällt da einfach kein Fall ein, in dem man es mit einer Interface instanz nicht einfacher lösen könnte... :gruebel:
Zitat:

Zitat von r2c2
Gibt es eigentlich eine sinnvolle Begründung dafür den destructor zu überladen? Warum sollte man das tun? Reicht ein Destructor nicht?

Man sollte es nicht.
TObject.Free ruft TObject.Destroy auf. Jeder Vorfahre/Nachfahre wird DIESEN Destructor überschrieben haben.
Und jeder, der die Klasse benutzt wird wohl auch Free oder den Destructor von TObject aufrufen um aufzuräumen.
Der Code in einem nicht überschriebenen Destructor wird also effektiv nie ausgeführt werden.
Deshalb gleich nochmal: Delphi-Referenz durchsuchenvirtual & Delphi-Referenz durchsuchenoverride

r2c2 15. Jun 2005 16:39

Re: Destruktor überladen
 
Zitat:

Zitat von Robert_G
Zitat:

Zitat von r2c2
3. In größeren Projekten(meinend nicht in meinen bisherigen) kann dies aber IMHO sinnvoll sein

Mir fällt da einfach kein Fall ein, in dem man es mit einer Interface instanz nicht einfacher lösen könnte... :gruebel:

*an den Haaren herbeizieh* Wenn man viele Objekte erstellt und die vorher(d.h. nicht erst im Desructor der Containerklasse) freigeben will. Ich hab mich allerdings mit Interfaces noch zu wenig befasst, alsdass ich sagen könnte ob mans damit einfacher hinkriegt.

Zitat:

Zitat von Robert_G
Zitat:

Zitat von r2c2
Gibt es eigentlich eine sinnvolle Begründung dafür den destructor zu überladen? Warum sollte man das tun? Reicht ein Destructor nicht?

Man sollte es nicht.
TObject.Free ruft TObject.Destroy auf. Jeder Vorfahre/Nachfahre wird DIESEN Destructor überschrieben haben.
Und jeder, der die Klasse benutzt wird wohl auch Free oder den Destructor von TObject aufrufen um aufzuräumen.
Der Code in einem nicht überschriebenen Destructor wird also effektiv nie ausgeführt werden.
Deshalb gleich nochmal: Delphi-Referenz durchsuchenvirtual & Delphi-Referenz durchsuchenoverride

Jein, wenn man sich n eigenes Free bastelt vielleicht schon. :zwinker: Das war aber auch gar nicht meine Frage. Man könnte doch theoretisch den destuctor overriden und overloaden. Dann könnte man sich n eigenes Free basteln und bedingt die einzelnen Destruktoren aufrufen. Jetzt meine Frage: Macht das sinn? Und wenn ja: welchen?

mfg

Christian

P.S.: virtual und override sind mir durchaus bekannt. :wink:


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