AGB  ·  Datenschutz  ·  Impressum  







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

Wo gebt ihr Objekte frei?

Ein Thema von NerdIII · begonnen am 11. Dez 2007 · letzter Beitrag vom 12. Dez 2007
Antwort Antwort
Seite 3 von 3     123   
Benutzerbild von DataCool
DataCool

Registriert seit: 10. Feb 2003
Ort: Lingen
909 Beiträge
 
Delphi 10.3 Rio
 
#21

Re: Wo gebt ihr Objekte frei?

  Alt 12. Dez 2007, 12:59
^^^^
Der Horizont vieler Menschen ist ein Kreis mit Radius Null, und das nennen sie ihren Standpunkt.
  Mit Zitat antworten Zitat
Tyrael Y.

Registriert seit: 28. Jul 2003
Ort: Stuttgart
1.093 Beiträge
 
Delphi 2007 Professional
 
#22

Re: Wo gebt ihr Objekte frei?

  Alt 12. Dez 2007, 12:59
Rofl, FreeAndNil hat seinen Sinn, mach bitte einen neuen Thread dazu auf und ich bin bereit das zu beantworten bzw. guck mal in der DP, ich glaub das Thema hatten wir schon.
Levent Yildirim
Erzeugung von Icons aus Bildern:IconLev
  Mit Zitat antworten Zitat
Benutzerbild von DataCool
DataCool

Registriert seit: 10. Feb 2003
Ort: Lingen
909 Beiträge
 
Delphi 10.3 Rio
 
#23

Re: Wo gebt ihr Objekte frei?

  Alt 12. Dez 2007, 13:10
Hi,

@Popov:

Ich gebe Dir Recht, in einer procedure(für lokale Variablen) kann man auf
FreeAndNil verzichten und "besser" Objekt.free aufrufen.
Deshalb stand das in meinem Bsp. auch als Kommentar dahinter.


Bei mir wird allerdings durchgehend FreeAndNil verwendet,
über den "Sinn und Unsinn" lässt sich sicher streiten.
Aber Fakt ist:
Wenn man "Multi-Threaded" arbeitet ist es schon ne feine Sache mit FreeAndNil zu Arbeiten,
und vor dem Zugriff auf die Variable mit Assigned(xyz) zu prüfen,
ob es noch existiert.

Zwar hast Du Recht das es "meistens" überflüssig(90%) ist,
allerdings stürzt Dein Programm ab wenn die 10% eintreten,
meine nicht

Greetz DataCool
Der Horizont vieler Menschen ist ein Kreis mit Radius Null, und das nennen sie ihren Standpunkt.
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.117 Beiträge
 
Delphi 11 Alexandria
 
#24

Re: Wo gebt ihr Objekte frei?

  Alt 12. Dez 2007, 13:28
Moin Popov,

falls Du inzwischen Deinen Kaffee hattest kannst Du ja weiterlesen, ansonsten heb's Dir für nach dem Kaffee auf

In DataCools Beispiel wurde TargetBMP als Wertparameter übergeben, dem man also in der Methode einen Wert zuweisen kann, ohne dass es an den Aufrufer durchschlägt. Wenn dieses Objekt dann auch nicht in der Prozedure wieder freigegeben wird, hat man ein Speicherleck, ausserdem bekommt der Aufrufer nicht, was er haben wollte.
Nimmt man einen const Parameter kommt man damit nicht durch, da einem der Compiler auf die Finger haut.
Freigeben kann ich das damit übergebene Objekt ja immer. Egal ob es nun ein var- out- const- oder WertParameter ist.
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
Stefan.Buchholtz

Registriert seit: 2. Dez 2004
Ort: Mönchengladbach
7 Beiträge
 
Delphi 7 Enterprise
 
#25

Re: Wo gebt ihr Objekte frei?

  Alt 12. Dez 2007, 14:00
Zitat von NerdIII:
Hi, ich stoße beim Entwickeln immer wieder auf Probleme beim Umsetzen von OOP.
'Objekte da freigeben wo sie erzeugt werden.' heißt es so schön.
Nun sehe ich in Code von anderen (und auch von mir ab und zu) Methoden, die TStringLists oder TBitmaps erzeugen und zurückgeben. Soll nun die Klasse deren Methode ich aufrufe sich einen Pointer auf die Bitmap/Liste merken, damit sie den Speicher auch selbst wieder freigeben kann oder soll die aufrufende Stelle das tun. Und wie kennzeichne ich eine Methode am besten, damit klar wird, dass jemand der sie verwendet noch Speicher freigeben muss?
(Es gibt Beispiele, z.B. bei Formatierungsfunktionen in C, die den Rückgabewert selber verwalten und freigeben. Das macht das Entwickeln angenehm sorglos.)
Methoden, die ein Objekt erzeugen und an den Aufrufer zurückgeben, so dass der Aufrufer für die Freigabe des Objekts verantwortlich ist, heissen bei mir immer Create... So ist beim Methodenaufruf sofort ersichtlich, dass ein Objekt erzeugt wird.

Für komplett eigene Klassen benutze ich Referenzzählung zur Speicherverwaltung. Ich habe eine Klasse TCountedObject, die TObject um eine Zählervariable erweitert. TCountedObject besitzt die Methoden Retain, die den Referenzzähler um 1 erhöht und Release, die den Zähler um 1 dekrementiert und Free aufruft, wenn der Zähler 0 erreicht. Ausserdem gibt es noch die Methode AutoRelease, die das Objekt für einen späteren Aufruf von Release vormerkt. Dafür gibt es noch die Singleton-Klasse TAutoReleasePool, die eine Liste von TCountedObjects verwaltet. Der Aufruf von AutoRelease fügt das Objekt dieser Liste hinzu. Im OnIdle-Event von Application wird dann Release für alle Objekte im AutoReleasePool aufgerufen.

So kann eine Methode ein TCountedObject erzeugen, sofort AutoRelease dafür aufrufen und das Objekt dann an den Aufrufer zurückgeben. Will der Aufrufer das Objekt nicht über die aktuelle Methode hinaus verwenden, braucht er gar nichts zu tun - sobald die aktuelle Ereignisverarbeitung abgeschlossen ist, wird im Idle-Event der Anwendung für das Objekt Release aufgerufen, was den Referenzzähler auf 0 dekrementiert und das Objekt damit freigibt. Will der Aufrufer das Objekt länger behalten, ruft er Retain auf. Damit überlebt das Objekt den Release-Aufruf im OnIdle. Weil der Aufrufer Retain aufgerufen hat, ist er dann auch für die Freigabe mit Release verantwortlich.

Dieser Mechanismus wirkt erstmal recht kompliziert, aber er sorgt dafür, das man normalerweise eine korrekte Speicherverwaltung durch Befolgen von wenigen einfachen Regeln erhält:

1. Ein Objekt, das ein anderes Objekt erzeugt (durch direkten Aufruf des Konstruktors oder durch eine Funktion namens CreateXYZ), ist dafür verantwortlich, durch Aufruf von Release für die Freigabe zu sorgen
2. Ein Objekt, das eine Referenz auf anderes Objekt dauerhaft speichert (also in einer nicht lokalen Variablen), muss für dieses Objekt Retain aufrufen. Danach ist es auch für den Aufruf von Release verantwortlich, als hätte es das Objekt selbst erzeugt.
3. Eine Funktion, die ein Objekt erzeugt und an den Aufrufer zurückgibt, ohne eine Referenz auf das Objekt zu behalten, kann statt Release AutoRelease aufrufen und kommt damit ihrer Verpflichtung, Release aufzurufen, nach und kann das Objekt trotzdem noch zurückgeben.

Problematisch sind dann nur noch Strukturen, bei denen Objekte gegenseitige Referenzen speichern. Hier würde dieses Verfahren zu einem Speicherleck führen, wenn sich die beiden Objekte gegenseitig Retainen. Normalerweise ist es dann sinnvoll, eine Hierarchie zu definieren, in der eins der Objekte dem anderen übergeordnet ist. Das übergeordnete Objekt ruft dann Retain und Release für das untergeordnete auf, aber nicht umgekehrt.

Um Objekte mit Referenzzählung von solchen ohne Referenzzählung (die gesamte Delphi-Standardbibliothek) zu unterscheiden, verwende ich für von TCountedObject abgleitete Klassen immer das Namenspräfix TC.

Stefan
Stefan Buchholtz
  Mit Zitat antworten Zitat
Popov
(Gast)

n/a Beiträge
 
#26

Re: Wo gebt ihr Objekte frei?

  Alt 12. Dez 2007, 14:02
Zitat von Tyrael Y.:
FreeAndNil hat seinen Sinn, mach bitte einen neuen Thread dazu auf und ich bin bereit das zu beantworten ...
Nein, vielen Dank, über die Bienen und Blümchen bin ich schon aufgeklärt und über FreeAndNil braucht mich auch keiner aufklären

Zitat von DataCool:
Aber Fakt ist:
Wenn man "Multi-Threaded" arbeitet ist es schon ne feine Sache mit FreeAndNil zu Arbeiten,
und vor dem Zugriff auf die Variable mit Assigned(xyz) zu prüfen,
ob es noch existiert.
Wie ich schon gesagt habe, das sind spezielle Situationen wo man bewußt mit der Information Nil arbeitet. Das ist etwas anderes. Nur wie gesagt - das sind bewusste Situationen wo Nil eine Information darstellt. Allerdings scheint es eine Mode zu sein, denn man sieht das allgemein. Es wird sogar Newbies empfohlen lieber FreeAndNil anstelle von Free zu nehmen. Wozu? Das ist Sinnlos.

Und nein, mir ist noch kein einziges Mal mein Programm um die Ohren geflogen weil ich auf ein Objekt zugegriffen habe das nicht da ist. Und ja, auch ich arbeite gelegentlich mit der Information Nil, aber dann wird Nil bewußt gesetzt. FreeAndNil ist als ob man mit Variant Variablen arbeiten würde. Dann kann man die Variable als String nutzen und kann sogar damit rechnen wenn zufällig nur Zahlen drin vorkommen. Eigentlich kann man dann sofort zu VB wechseln.

EDIT:

Zitat von Christian Seehase:
Nimmt man einen const Parameter kommt man damit nicht durch, da einem der Compiler auf die Finger haut.
Freigeben kann ich das damit übergebene Objekt ja immer. Egal ob es nun ein var- out- const- oder WertParameter ist.
Du schlägst aber einen sehr weiten Bogen. Ich arbeite eigentlich zu 100% nach der Methode 3. Ich weiß, daß ich im Leben noch nicht alles programmiert hatte, aber Probleme deswegen hatte ich noch nie. Sicher, auch ich bin ein Absicherungsfanatiker und die hälfte meines Codes besteht manchmal nur aus Absicherungen und Abfragen. Ich hasse System-Errors, die kommen bei mir eigentlich nie vor. Und wenn, dann sind es meine eigene Fehlermeldungen. Aber man kann es auch übertreiben.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#27

Re: Wo gebt ihr Objekte frei?

  Alt 12. Dez 2007, 14:14
Ich werde immer lieber einfach Free aufrufen für interne Objekte in den Destruktoren anstatt mir die Finger weiter zu demolieren, nur damit ich dann statt dessen
Delphi-Quellcode:
if assigned(AObj) then
  AObj.Destroy;
schreiben muss für eine sichere Freigabe.

Schon allein "bewußt mit Nil arbeiten" setzt voraus, dass du behaupten würdest, dass deine Objekte niemals durch einen Fehler NIL sind. Schon allein ein EOutOfResource Exception z.B. im Konstruktor eines Bitmaps würde dir ein NIL Objekt bescheren - mit dem du aber niemals rechnest, da das Anlegen von Bitmaps immer klappt. Wenn nun mal weiter annehmen, dass die Methoden welches das Bitmap nutzen entsprechend die Instanz abprüfen und nichts passiert und dann im Destruktor direkt steht "Bitmap.Destroy", dann knallt es am Ende (schön sichtbar für den Kunden).

Ich bin mir soweit auch sicher, dass Bitmaps eigentlich immer eine Instanz liefern, aber trotzdem rufe ich nicht direkt Destroy auf und bin damit nochmal ein wenig sicherer (trotz meiner fahrlässigen Annahme). Ansonsten gilt grundsätzlich jbg's Beitrag.

Man kann meistens gar nicht so doof denken, wie auch z.T. die WinAPI einem in die Suppe spucken kann. Da kann man noch so sicher sein, im Fehlerfall bricht dann aber entsprechend alles zusammen sondern nur ein Teil.

Zitat von Popov:
Ich weiß, daß ich im Leben noch nicht alles programmiert hatte, aber Probleme deswegen hatte ich noch nie. Sicher, auch ich bin ein Absicherungsfanatiker und die hälfte meines Codes besteht manchmal nur aus Absicherungen und Abfragen. Ich hasse System-Errors, die kommen bei mir eigentlich nie vor. Und wenn, dann sind es meine eigene Fehlermeldungen. Aber man kann es auch übertreiben.
Und genau dann, kann ich das nicht benutzen von Free nicht verstehen, schliesslich ist es eine zusätzliche Sicherheit.

@Stefan.Buchholtz: Respekt! Ich würde niemals einen solchen Aufwand treiben zu wollen, nur um mir einen Garbagecollector zu bauen, der dann nur auf die von mir selbst geschriebenen Dinge wirken kann. Die eine Hälfte bequem, die andere Hälfte der Objekte Old-School. Aber wie gesagt: ich habe Respekt vor der Arbeit. Mich würde nur die Nutzung nicht unbedingt überzeugen. Würde es grundsätzlich für alle Objekte gelten, dann würde es mich überzeugen und ich würde es nutzen. Siehe entsprechende Sprachen mit Garbage-Collector. Da ist es im Sprachumfang und gilt automatisch für alle genutzten Elemente.
  Mit Zitat antworten Zitat
Popov
(Gast)

n/a Beiträge
 
#28

Re: Wo gebt ihr Objekte frei?

  Alt 12. Dez 2007, 14:30
Zitat von Muetze1:
Und genau dann, kann ich das nicht benutzen von Free nicht verstehen, schliesslich ist es eine zusätzliche Sicherheit.
Mir ist bewußt, daß du hier auf etwas aus bist und mich sagen lassen willst, daß ich doch Free benutze. Also tue ich dir den Gefallen und lasse mich überaschen:

Aber ich spreche doch nicht von Free, das benutze ich doch selbst. Ich spreche die ganze Zeit von FreeAndNil.
  Mit Zitat antworten Zitat
Stefan.Buchholtz

Registriert seit: 2. Dez 2004
Ort: Mönchengladbach
7 Beiträge
 
Delphi 7 Enterprise
 
#29

Re: Wo gebt ihr Objekte frei?

  Alt 12. Dez 2007, 15:00
Zitat von Muetze1:
@Stefan.Buchholtz: Respekt! Ich würde niemals einen solchen Aufwand treiben zu wollen, nur um mir einen Garbagecollector zu bauen, der dann nur auf die von mir selbst geschriebenen Dinge wirken kann. Die eine Hälfte bequem, die andere Hälfte der Objekte Old-School. Aber wie gesagt: ich habe Respekt vor der Arbeit. Mich würde nur die Nutzung nicht unbedingt überzeugen. Würde es grundsätzlich für alle Objekte gelten, dann würde es mich überzeugen und ich würde es nutzen. Siehe entsprechende Sprachen mit Garbage-Collector. Da ist es im Sprachumfang und gilt automatisch für alle genutzten Elemente.
Es ist ja gar kein Garbage Collector - man muss schon noch daran denken, Objekte freizugeben.

Der Implementierungsaufwand von dem Ding war nicht groß - insgesamt sind das vielleicht 200-300 Zeilen. Dazu kommen noch Container-Klassen (Listen, Hashes), die die Referenzzählung unterstützen, das sind vielleicht auch noch ein paar 100 Zeilen. Und wenn man sowas einmal gebaut hat, ist es getan - dann kann man es in allen möglichen Projekten benutzen.

Das wird in hauptsächlich einem größeren Projekt (sicherlich mehrere 100.000 Zeilen Code) eingesetzt, in dem (mittlerweile) sehr stark objektorientiert gearbeitet wird - insbesondere wird die Datenbank fast vollständig durch ein Objektmodell abgebildet. Wir haben also sehr viele eigene Klassen, bei denen auch häufig Objekte von mehreren anderen Objekten parallel benutzt werden Dann braucht man ein System, um den Überblick nicht zu verlieren.

Das ganze Konzept habe ich überigens komplett aus dem API von MacOS X übernommen.

Stefan
Stefan Buchholtz
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 3     123   


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 14:20 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