![]() |
Wo gebt ihr Objekte frei?
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.) Es gibt für mich 3 Möglichkeiten: 1. Methode erzeugt Objekt. 'Empfänger' muss sich um Freigabe kümmern. + kein unnötiger Speicherverbrauch - kann übersehen werden 2. Methode erzeugt Objekt und hält eine Referenz darauf. Beim nächsten Aufruf wird es freigegeben und ein neues erzeugt (C-Style). + Aufrufer braucht sich keine Sorgen zu machen - Immer nur ein Objekt zur Zeit kann verwendet werden, ausßer es gibt einen Kopierkonstruktor - evtl. unnötiger Speicher, wenn das Objekt nur kurz verwendet wird 3. Aufrufer erzeugt Objekt und lässt es von Methode 'befüllen'. + keine Missverständnisse bei erfahrenen Entwicklern - unübersichtlicher Code durch Erzeugung des Objekts und weiteren Parameter Wie entwickelt ihr? Gibt es Standards? |
Re: Wo gebt ihr Objekte frei?
Primär 3, Ab und zu 1 und statt 2 würde ich ein Singleton-Pattern verwenden.
|
Re: Wo gebt ihr Objekte frei?
Die 2 nutze ich eigentlich recht selten.
Und bei den Anderen (1/3) ... jenachdem wie es mir am Besten vorkommt ... halt das was ich in dem Moment und für das vorliegende "Problem"/Projekt für besser/einfacher erachte. PS: ich geb manchma Objekte/Speicher garnicht frei ... Delphi/Windows kümmert sich schon drum :roll: (jedenfalls da wo ich weiß daß die beiden sich schon korrekt darum kümmern) |
Re: Wo gebt ihr Objekte frei?
Im aktuellen Projekt des Informatikkurses, in dem ich bin, wird durchgängig 1 verwendet und die Freigabe "vergessen" (weil niemand weiß, wie - außer n paar, die zu faul dazu sind *hust*)
Wenn du statt Objekten Interfaces verwendest, ist das Freigabeproblem auch nahezu aus der Welt. |
Re: Wo gebt ihr Objekte frei?
Als Faustformel wird meistens vermittelt: Das Objekt sollte auf der gleichen Ebene wieder freigegeben werden, wie es erzeugt wurde. Somit ist die erste Lösung nicht nutzbar und auch grundsätzlich schlechter Stil. Wenn in einem Projekt viele sowas machen, dann sieht im Endeffekt keiner mehr durch um sagen zu können: MethodeX gibt mir nur eine Referenz auf ein internes Objekt zurück, also nicht freigeben oder die Methode gibt ein frisch für die Rückgabe angelegtes Objekt zurück. Es macht deutlich mehr Aufwand und Pflege.
Meine XMLLib hatte solche Methoden z.T. wie dein erstes Beispiel implementiert, aber das war sehr schlecht. Die meisten Nutzer haben sich keine Platte gemacht die Rückgabewerte freizugeben. Zum Teil wurde die nichtmal in eine Variable geworfen sondern direkt temporär benutzt und da ist dann schnell mal die Applikation beim Speicher fressen. Die Anwender haben die Lib nicht geschrieben und wissen nicht um das Handling. Es gibt zwar eine Dokumentation, aber wer liest die, wenn alles läuft? Vor allem kommt keiner auf die Idee etwas frei zu geben, was ein anderer angelegt hat. Nun habe ich es durchgedrückt und der Aufrufer hat die Listen zu erzeugen. Damit ist es dem Nutzer definitiv bewußt, dass er eine Instanz angelegt hat und dadurch ist es ihm auch bewußt diese wieder freizugeben. Und wann das sein wird, weiß der Anwender am besten. Damit ist aber auch immer definitiv klar, wer was zu machen hat. |
Re: Wo gebt ihr Objekte frei?
OT: Als ich angefangen habe zu Programmieren wusste ich nicht, dass man Objekte freigeben muss/kann. Jedoch wenn man in einer for Schleife immer ein Bitmap lädt stößt man recht schnell an Grenzen.
Heute verwende ich oft 1. Allerdings sehne ich mir machmal die Vorteile eines Garbage Collectors herbei :? mfg, Björn |
Re: Wo gebt ihr Objekte frei?
![]() Dann doch lieber selbst freigeben :roll: noch'n Thread für's aufräumen und dann ist man nichtmal sicher ob der wirklich alles richtig aufräumt .... |
Re: Wo gebt ihr Objekte frei?
Moin Nerd,
Zitat:
Ich finde diese Aussage sehr unverständlich. Da gefällt mir die von Thomas doch erheblich besser. Um die abstrakte Aussage mit der gleichen Ebene von Erzeugen und Löschen mal zu konkretisieren: Wenn ich ein Objekt im initialization-Abschnitt erzeuge, wird es im finalization-Abschnitt wieder freigegeben Wenn ich ein Objekt in einem Konstruktor erzeuge, wird es im zugehörigen Destruktor wieder zerstört. Wenn ich ein Objekt in einer Prozedur/Methode erzeuge, wird es auch dort wieder freigegeben. Bei letztgenanntem Falle sehe ich allerdings auch Ausnahmen: Wenn ein Objekt erzeugt wird, dass dann in einer Liste vorgehalten wird (z.B. eine TObjectList) werden sie, natürlich, nicht gleich in der Prozedur/Methode wieder freigegeben (wobei diese Liste dann ja als Owner einer Komponente fungiert). Die zweite Ausnahme die ich hier sehe, ist das Erzeugen einer Komponente, wenn hier im Constructor ein Owner angegeben wird, der dann ja für die Freigabe verantwortlich ist. Sollte ich so ein global erzeugtes Objekt zwischendurch mal wieder leeren müssen, geschieht dies durch eine entsprechende Methode, und nicht durch Free und erneutes Create. Beispielsweise habe ich da ein Projekt, in dem ich ein paar StringListen immer wieder benötige. Die werden im OnCreate des Formulares erzeugt, im OnDestroy wieder freigegeben, und zwischendurch mit Clear immer mal wieder geleert. Um das auf Deine drei Möglichkeiten anzuwenden: Zu 1.: Kommt überhaupt nicht in Frage, da hier viel zu leicht die Übersicht verloren gehen kann, und man sich leicht Speicherlöcher einhandelt. Stell Dir vor, dass passiert Dir in einem Dienst, der auf einem Server läuft... ;-) Zu 2.: Schon etwas besser als 1. aber wenn Du die angesprochende Kopiermethode verwendest muss sich doch wieder eine andere Stelle darum kümmern aufzuräumen. Ausserdem kann es Dir hier passieren, dass ein Programmteil noch mit einem Objekt arbeiten will, dass bereits durch den Aufruf der gleichen Methode in einem anderen Programmteil zerstört wurde. Aus diesem Grunde halte ich diese Möglichkeit für recht unübersichtlich. Zu 3.: Meiner Ansicht nach die sinnvollste Variante. Deinen Negativpunkt kann ich allerdings nicht nachvollziehen, eher im Gegenteil. Man sieht gleich woran man ist. Ich würde diese Vorgehensweise übrigens nicht auf Objekte einschränken, sondern auf alle Resourcen anwenden die angefordert werden, z.B. auch Handles. Es gibt übrigens sogar API-Funktionen, die Resourcen selber reservieren (z.B. viele NetXXX-Funktionen), und für die es explizit Funktionen gibt, mit denen diese vom Aufrufer wieder freizugeben sind. Das dient dort übrigens nur dem Komfort sich nicht selber um erforderliche Buffergrösse kümmern zu müssen, wie bei so manch anderer API-Funktion. |
Re: Wo gebt ihr Objekte frei?
Da brauchen wir nicht lange drumherum reden, die Methode 3 ist eigentlich die Standardmethode. Ich hatte noch nie eine Aufgabe die ich nicht mit dieser Methode lösen konnte. Sie ist sauber und man weiß immer was man freigeben muß.
Die Methode 1 mag ich eigentlich nicht, ist aber möglich. Hier will ich mal Muetze1 ein wenig widersprechen, denn diese Methode sieht man gelegentlich. Auch in gut programmierten Programmen. Ich kann mich sogar erinnern irgendwo ein Beispiel in der Delphi Hilfe gesehen zu haben das so gelöst wurde. Das Problem ist allerdings, daß man irgendwann nicht mehr dran denkt, daß man etwas wieder freigeben muß. Bei Miniprojekten geht das noch, vielleicht auch bei Funktionen die man immer wieder nutzt, sonst bin ich aber kein Fan davon. Die Methode 2 ist vielleicht interessant, aber das ist kein programmieren, sondern eher basteln. Meiner Meinung nach verläßt man hier den Pfad der sauberen Programmierung. |
Re: Wo gebt ihr Objekte frei?
Zitat:
![]() ABER: Das TListView macht dies so, damit der Parent eingetragen ist. Der ListView kümmert sich auch um die zurück gegebenen Instanzen. Also genau eins dieser Ausnahme-Beispielen von Christian. |
Re: Wo gebt ihr Objekte frei?
Moin Popov,
Zitat:
|
Re: Wo gebt ihr Objekte frei?
Was sind denn "gut programmierte Programme" bzw. Kriterien dafür?
|
Re: Wo gebt ihr Objekte frei?
Zitat:
Delphi-Quellcode:
Jetzt nicht das, aber irgendwas in der Richtung.
function BildLaden(FileName: TFileName): TBitmap;
begin Result := TBitmap.Create; Result.LoadFromFile(FileName); end; |
Re: Wo gebt ihr Objekte frei?
Hi,
eigentlich geht bei sauberer Programmierung kein Weg an Punkt 3 vorbei. Ansonsten kann ich nur absolut Christian S. zustimmen, hätte es nicht besser ausdrücken können :thumb: Die obere Function "Bild laden" ist in meinen Augen ein absolutes "no go"! Falls ich sowas im Source Code einer Bewerbung sehe, landet die schonmal im Papierkorb ! Dann eher:
Delphi-Quellcode:
Aber bei diesem Beispiel könnte man ja nach dem Code "aussen rum",
function BildenLaden(sFilename : TFilename; TargetBmp : TBitmap) : boolean;
begin result := false; if not Fileexist(sFilename) then exit; if not Assigned(TargetBmp) then exit; try TargetBmp.LoadfromFile(sFilename); result := true; except {} end; end; procedure bild_xyz; Var tmpBmp : TBitmap; begin tmpBmp := TBitmap.create; try if BildLaden(sFilename, tmpBmp) then BildAnzeigen(tmpBmp); finally FreeAndNil(tmpBmp);// oder tmpBmp.free end; end; auch eine eigene Klasse schreiben die das Bitmap als private var hat. In diesem Fall würde das Bitmap im Constructor erzeugt, im Destructor zerstört/freigegeben und die Klasse hätte die Methoden LoadFromFile, LoadFromStream, Clear Display etc. @arbu man: Wenn man sauber programmiert, dann brauch man den Garbage Collector nicht !!! ^^^^^^Ein Grund warum ich Java nicht mag und so gut wie gar nicht benutze. Ich möchte Speicher immer nur dann reservieren, benutzen wenn ich ihn brauche und wenn er nicht mehr benötigt wird, soll er auch umgehend freigegeben werden. Es ist zwar schön wenn Mann sich darum nicht kümmern muss und einfach "seinen Müll" vor die Tür stellt und wartet das er abgeholt wird. Nur umso schlimmer wenn die Müllabfuhr nicht oder zu spät kommt. Greetz DataCool |
Re: Wo gebt ihr Objekte frei?
Moin DataCool,
wobei ich da noch einen kleinen Verbesserungsvorschlag hätte: TargetBmp sollte besser als const deklariert werden. Es funktioniert zwar so auch, aber wenn mal jemand daran arbeitet könnte, ohne Compilerwarnung, etwas in den Parameter geschrieben werden, so dass man dann zum einen ein Speicherleck bekommen kann, und sich zum anderen erst einmal wundert, warum's nicht wie erwartet funktioniert. In einem anderen Thread hatte ich gerade gestern geschrieben, dass ich nur var- oder const-Parameter verwende. Var bei Rückgabewerten (die ggf. zu Beginn natürlich auch Eingabewerte enthalten können), const bei reinen Eingabewerten, oder wenn Referenzen übergeben werden sollen. Für Wert-Parameter habe ich bislang keine rechte Verwendung gefunden ;-) Zum Thema Garbage-Collection: Ich weiss nicht, wie gut die heutzutage implementiert ist, aber meinen Schneider Zeiten (CPC 464, Basic mit Garbage-Collection) war es immer eine mittlere Katastrophe, wenn die GC zugeschlagen hat. Der Rechner war dann immer für längere Zeit ausser Gefecht gesetzt, bis ihm wieder Reaktionen zu entlocken waren :mrgreen: Das sollte bei den heutigen Multi-Tasking-Systemen aber wohl kein Thema mehr sein. |
Re: Wo gebt ihr Objekte frei?
@DataCool: Eine leerer except Block ist aber genauso unsittlich und würde auch den Weg in den Papierkorb finden :wink:
Und FreeAndNil() auf lokale Variablen (und das noch im Finally-Block am Ende der Procedure) ist auch schon mehrfach diskutiert worden - mit unterschiedlichem Ergebnis. Zitat:
|
Re: Wo gebt ihr Objekte frei?
Alle drei Varianten sidn ok und von Fall zu Fall auch sinnig.
Meistens benutze ich Fall 3, manchmal Fall 2 und eher selten Fall 1. Zu Fall 1 noch eine Anmerkung. Ich finde, wenn man diese Variante benutzt sollte die Klasse, die das Objekt in seiner Methode zurückgibt auch eine Methode besitzen, um diese Objekt frezugeben.
Delphi-Quellcode:
function TEineKlasse.ErzeugeEinObject(): TEineAndereKlasse; begin ... end procedure TEineKlasse.GibObjectWiederFrei(); begin ... end; Wenn man ein Objekt erhält, daß nur einmal existieren darf, sorgt die Methode "GibObjectWiederFrei" dafür, daß genau dieses Objekt freigegeben wird. Hat man den Fall, daß diese Klasse immer wieder neue Objekte erzeugen kann, dann sollte die Klasse selbst eine Referenz zu jedem erzeugten Object in einer Liste halten und beim Aufruf von "GibObjectWiederFrei" könnte man dann entweder den Index des Objektes übergeben oder das Objekt selbst... Ich finde alle Varianten sind Geschmackssache und jedes hat seine Lebensberechtigung. Im normalen Programmieralltag wird man aber bevorzugt Variante 3, seltener Variante 2 und ganz selten Variante 1 benutzen. Ich und meine Kollegen machen das zumindest so. |
Re: Wo gebt ihr Objekte frei?
Mit so einer regen Diskussion hatte ich garnicht gerechnet. Ich habe alle Antworten gespannt durchgelesen und bin nun zu dem Schluss gekommen, dass wenn mehrere Programmierer an dem Projekt arbeiten sollen Variante 3 fast immer zu bevorzugen ist.
Ich hatte in einem Projekt vor kurzem den Fall, Variante 2 verwendet wurde und ich fälschlicherweise das Objekt freigegeben habe.
Delphi-Quellcode:
(TImage verwendet für dir Zuweisung ein Assign, deshalb keine Probleme an der Stelle)
tmpBMP := Objekt.GetRendering;
try imgBild.Picture.Bitmap := tmpBMP; finally tmpBMP.Destroy; end; Gelößt sah es dann so aus:
Delphi-Quellcode:
Variante 3 würde daraus folgendes machen:
imgBild.Picture.Bitmap := Objekt.GetRendering;
Delphi-Quellcode:
Das ist kürzer, unmissverständlich, erzeugt keine unnötige Bitmap und man bekommt das Objekt das etwas tut an den Anfang der Code-Zeile. Klarer Fall :)
Objekt.RenderInto( imgBild.Picture.Bitmap );
|
Re: Wo gebt ihr Objekte frei?
Zitat:
Und nochmal allgemein zu FreeAndNil (also nicht @Christian). Ich halte FreeAndNil für eine Unsitte. Ich arbeite schon so lange mit Objekten, aber es ist mir noch nie ... ups, das Objekt ist ja schon freigegeben ... passiert. Fehler können passieren, aber jenseits der Fehler weiß ich immer was mein Objekt macht. Mir ist schon klar, daß man gelegentlich auch abfragt ob ein Objekt Nil ist. Allerdings sind das dann Sondersituationen. In diesem Fall kann man meinetwegen das Objekt nil setzten, damit man an einer anderen Stelle prüfen kann ob es nil ist. In diesem Fall ist es ein Teil der Programmierung, denn Nil ist auch eine Information und wenn man mit dieser Information arbeiten muß oder will, dann nutzt man sie. Dann allerdings bewusst. Aber so oft kommt sowas nicht vor, also wozu das Ganze (beinahe hätte ich "Unsinn" gesagt)? Anscheinend ist es eine Mode, wie vor einigen Jahren der Gummiüberzug für die Fernbedienung. Plötzlich hatte für einen gewissen Zeitraum die gesamte Republik ihre Fernbedienungen mit einem Gummipolster geschützt, für den Fall, daß die Fernbedienung auf den Boden fällt. Plötzlich gab es kein Gummi für die Autoreifen, weil alle ihre Fernbedienungen schützten. Also wozu dieses Nil bei der Freigabe von Objekten? Wer nutzt ein Objekt das bereits freigegeben worden ist? Wer FreeAndNil nutzt, der mag auch die Methode zwei, denn da muß man wirklich wissen ob ein Objekt bereits freigegeben worden ist und auf das kann man mit Nil hinweisen. Ansonsten überlege ich wirklich wo man das in der Allgemeinprogrammierung anwenden kann. In besonderen Situationen meinetwegen, aber sonst? |
Re: Wo gebt ihr Objekte frei?
Zitat:
|
Re: Wo gebt ihr Objekte frei?
^^^^
|
Re: Wo gebt ihr Objekte frei?
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.
|
Re: Wo gebt ihr Objekte frei?
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 |
Re: Wo gebt ihr Objekte frei?
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. |
Re: Wo gebt ihr Objekte frei?
Zitat:
Delphi-Quellcode:
So ist beim Methodenaufruf sofort ersichtlich, dass ein Objekt erzeugt wird.
Create...
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 |
Re: Wo gebt ihr Objekte frei?
Zitat:
Zitat:
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:
|
Re: Wo gebt ihr Objekte frei?
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:
schreiben muss für eine sichere Freigabe.
if assigned(AObj) then
AObj.Destroy; 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:
@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. |
Re: Wo gebt ihr Objekte frei?
Zitat:
Aber ich spreche doch nicht von Free, das benutze ich doch selbst. Ich spreche die ganze Zeit von FreeAndNil. |
Re: Wo gebt ihr Objekte frei?
Zitat:
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. :mrgreen: Stefan |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:40 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz