![]() |
Re: Bin ich schon zerstört?
Zitat:
Du kannst ja nicht TKlasse.Free aufrufen, wenn Free() keine static-methode ist... |
Re: Bin ich schon zerstört?
Zitat:
Delphi-Quellcode:
Das dient genau dazu, Nil-Referenzen auf Klassen 'aus Versehen' nochmals freizugeben, ohne das einem das Programm um die Ohren ballert.
Procedure TObject.Free;
Begin If Self<>Nil Then Destroy; End; Du kannst ohne Probleme TFooObject(4711).SomeMethod ausführen. Das klappt sogar, solange keine Felder der Klasse verwendet werden. Aber ich wiederhole ja nur das, was hier Andere schon geschrieben haben. Zurück zum Thema: Wenn Du mehrere Referenzen auf ein Objekt hast, dann benötigst Du Referenzzähler. COM-Objekte implementieren das, und Delphi unterstützt COM-Objekte. Schau mal in der Hilfe nach, wie mal COM-Objekte deklariert und verwendet, eigentlich ganz einfach. Prinzipiell geht das so: Bei jeder Referenz auf das Objekt erhöhst Du den Referenzzähler. Anstatt das Objekt freizugeben, rufst Du eine Methode 'Release' auf, in der Du den Zähler wieder erniedrigst. Wenn der Zähler 0 ist, gibst Du das Objekt wieder frei.
Delphi-Quellcode:
Aufpassen beim Anfassen der Refcounts: Am Besten sollte man das noch threadsicher kapseln (Oder, wie gesagt, COMs nehmen).
Function GetReferenceToMyObject : TMyObject;
Begin If not Assigned (PrivateObject) Then PrivateObject.Create; PrivateObject.IncreaseRefCount; End; Procedure TPrivateObject.Release; Begin DecreaseRefCount; If fRefCount = 0 Then Free; End; |
Re: Bin ich schon zerstört?
Zitat:
|
Re: Bin ich schon zerstört?
Das mit den Referenzzählern geht nicht, weil
a) viel zu viel Aufwand (wird nicht bezahlt) und b) das schon seine Richtigkeit hat, das das Objekt schon zerstört ist, weil wenn nicht, gäbs an anderer Stelle Probleme. |
Re: Bin ich schon zerstört?
Hey,
ich glaube es gibt keinen guten Weg das ohne try ... except ... abzufangen. Aber als Alternative, gibst du die Instanzen selbst frei? Dann solltest du einfach dafür sorgen, dass FreeAndNil aufgerufen wird (oder selbst danach den Variablenzeiger nil setzen). Ok, ich glaube ehrlich gesagt, dass wenn es so einfach wäre du selbst drauf gekommen wärst, aber kann ja sein. Ansonsten scheinen die anderen Möglichkeiten nicht wirklich zu funktionieren (zumal Referenzzähler ja nicht anzeigen können ob eine Instanz existiert oder nicht). Gruß Der Unwissende |
Re: Bin ich schon zerstört?
Zitat:
alzaimar hat dir ja schon vorgeschlagen, Inferfaces und Referenzzählung einzusetzen. Du erzeugst ein Objekt und speicherst es in mehr als einer (Objekt-)Variablen. Wenn nun gleichzeitig die Gefahr besteht, dass das Objekt freigeben werden kann aber die Objekt-Variablen weiterhin leben (also im Scope bleiben), hast du einen Software Designfehler begangen. Jeder Versuch, den Fehler mit Try..Except auszubügeln ist Banane. Entweder gelingt es, beim Freigeben des Objekts ALLE (Objekt-)Variablen auf nil zu setzen, oder du verwendest Interfacezeiger oder du gehst zurück auf Anfang und überlegst dir was ganz neues. |
Re: Bin ich schon zerstört?
Japp, das kann ic´h nur unterschreiben. Wenn Du eine Referenz auf ein bereits zerstörtes Objekt hältst und die von der Zerstörung nichts mitbekommt, dann ist vorher irgendwas schief gelaufen. Du solltest das Design nochmal überdenken und tatsächlich auf Referenzzähler zurückgreifen.
|
Re: Bin ich schon zerstört?
Zitat:
Du kannst die Konstruktoren Create und den Destruktor Destroy in '_create' und '_Destroy' umbenennen. Create wird eine Class function, die Dir das eine Objekt liefert und den ref-zähler hochsetzt. Destroy wird eine einfache Methode, die den RefCount wieder runterzählt und ggf das interne Objekt freigibt Aufwand: 10 minuten (wenns klappt :mrgreen: ). Sollte aber, sofern Du sauber programmiert hast. Wenn nicht, goto a) |
Re: Bin ich schon zerstört?
das find ich persönlich komisch:
erst um Hilfe fragen und dann aber doch nix ändern wollen. Das erinnert mich an meinen Chef der sagt auch immer: "beheb mal den Fehler, änder aber um himmels willen nichts am code" und da steh ich dann... mfg |
Re: Bin ich schon zerstört?
Zitat:
Zitat:
Ich habe mir angewöhnt Objekte immer wie folgt freizugeben:
Delphi-Quellcode:
Dann funktioniert auch der oben angegebene Code wieder. (asigned prüft auf nil)
...
myObject.Free; myObject := nil; ... Free prüft auch auf nil, deshalb ist folgender Code fehlerhaft:
Delphi-Quellcode:
Folgender code läuft hingegen fehlerfrei:
...
myObject := TmyObject.Create; ... myObject.Free; myObject.Free; // hier gibts Exception !!! ...
Delphi-Quellcode:
...
myObject := TmyObject.Create; ... myObject.Free; myObject := nil; myObject.Free; // kein Problem, da destroy nur aufgerufen wird, wenn <> nil myObject := nil; // diese 2. nil-Zuweisung ist überflüssig, // aber ich kombiniere immer Free mit nil Zuweisung ;-) ... Wenn Dir das zuviel Tipparbeit ist, kannst Du auch FreeAndNil verwenden.
Delphi-Quellcode:
(ist in SysUtils definiert)
...
FreeAndNil(myObject); ...
Delphi-Quellcode:
{ *********************************************************************** }
{ } { Delphi / Kylix Cross-Platform Runtime Library } { System Utilities Unit } { } { Copyright (c) 1995-2002 Borland Softwrare Corporation } { } { *********************************************************************** } unit SysUtils; ... procedure FreeAndNil(var Obj); var Temp: TObject; begin Temp := TObject(Obj); Pointer(Obj) := nil; Temp.Free; end; ... |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:56 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