AGB  ·  Datenschutz  ·  Impressum  







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

Bin ich schon zerstört?

Ein Thema von Sidorion · begonnen am 8. Nov 2005 · letzter Beitrag vom 9. Nov 2005
Antwort Antwort
Seite 2 von 3     12 3      
Benutzerbild von phXql
phXql

Registriert seit: 11. Mär 2004
Ort: Mühldorf
824 Beiträge
 
#11

Re: Bin ich schon zerstört?

  Alt 8. Nov 2005, 18:24
Zitat von SirThornberry:
man kann aber auch einfach auf eine "nil" instanz eine methode anwenden. Solange in der Methode (wie schon geschrieben wurde) nicht auf membervariablen zugegriffen wird kommt es da auch nicht zum Fehler.
TKlasse(nil).Methode; In diesem fall ist dann nur "Self" innerhalb der Methode nil
ja, aber damit gaukelst du doch dem compiler vor, eine instanz zu haben.

Du kannst ja nicht TKlasse.Free aufrufen, wenn Free() keine static-methode ist...
"Dunkel die andere Seite ist"
"Yoda! Halts Maul und iss deinen Toast!"
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#12

Re: Bin ich schon zerstört?

  Alt 8. Nov 2005, 18:37
Zitat von Khabarakh:
Genau. Es wäre ja wirklich sinnlos, wenn in Free Self auf nil geprüft wird, aber schon beim Methodenaufruf wegen Self = nil eine Exception ausgelöst würde.
Free ist aber genauso definiert:
Delphi-Quellcode:
Procedure TObject.Free;
Begin
  If Self<>Nil Then Destroy;
End;
Das dient genau dazu, Nil-Referenzen auf Klassen 'aus Versehen' nochmals freizugeben, ohne das einem das Programm um die Ohren ballert.
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:
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;
Aufpassen beim Anfassen der Refcounts: Am Besten sollte man das noch threadsicher kapseln (Oder, wie gesagt, COMs nehmen).
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Benutzerbild von Khabarakh
Khabarakh

Registriert seit: 18. Aug 2004
Ort: Brackenheim VS08 Pro
2.876 Beiträge
 
#13

Re: Bin ich schon zerstört?

  Alt 8. Nov 2005, 19:44
Zitat von alzaimar:
Zitat von Khabarakh:
Genau. Es wäre ja wirklich sinnlos, wenn in Free Self auf nil geprüft wird, aber schon beim Methodenaufruf wegen Self = nil eine Exception ausgelöst würde.
Free ist aber genauso definiert:
Delphi-Quellcode:
Procedure TObject.Free;
Begin
  If Self<>Nil Then Destroy;
End;
Das ist mir bewusst, die Modi waren nicht unabsichtlich so gewählt . Es ging ja darum, dass man Methoden auch ohne Instanz aufrufen kann (wäre dies nicht so, würde eben obige if-Verzweigung keinen Sinn, da nie erfüllt, machen).
Sebastian
Moderator in der EE
  Mit Zitat antworten Zitat
Sidorion

Registriert seit: 23. Jun 2005
403 Beiträge
 
#14

Re: Bin ich schon zerstört?

  Alt 9. Nov 2005, 08:27
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.
Manchmal sehen Dinge, die wie Dinge aussehen wollen mehr wie Dinge aus, als Dinge
<Esmerelda Wetterwachs>
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#15

Re: Bin ich schon zerstört?

  Alt 9. Nov 2005, 08:45
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
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#16

Re: Bin ich schon zerstört?

  Alt 9. Nov 2005, 09:21
Zitat von Sidorion:
Die Instanz wird ganz normal zerstürt, habe aber zwei Zeiger drauf und die wissen voneinander nix.
Das ist für mich der entscheidende Satz.
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.
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.611 Beiträge
 
#17

Re: Bin ich schon zerstört?

  Alt 9. Nov 2005, 10:05
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.
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#18

Re: Bin ich schon zerstört?

  Alt 9. Nov 2005, 11:29
Zitat von Sidorion:
Das mit den Referenzzählern geht nicht, weil
a) viel zu viel Aufwand (wird nicht bezahlt)
So ist das nunmal, wenn man einen 'falschen' Ansatz hat.
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 ). Sollte aber, sofern Du sauber programmiert hast. Wenn nicht, goto a)
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
DerDan

Registriert seit: 15. Nov 2004
Ort: Donaueschingen
251 Beiträge
 
Delphi XE3 Professional
 
#19

Re: Bin ich schon zerstört?

  Alt 9. Nov 2005, 12:07
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
nichts ist so schön wie man es sich vorstellt
  Mit Zitat antworten Zitat
Benutzerbild von MaBuSE
MaBuSE

Registriert seit: 23. Sep 2002
Ort: Frankfurt am Main (in der Nähe)
1.837 Beiträge
 
Delphi 10 Seattle Enterprise
 
#20

Re: Bin ich schon zerstört?

  Alt 9. Nov 2005, 12:40
Zitat von DGL-luke:
Delphi-Quellcode:
if assigned(myobj) then
 dosomething;
wenn der zeiger anständig nil gesetzt wurde nach dem zerstören.
Zitat von Sidorion:
@DGL-Luke: darum ist Assigned(MyObj) in dem Falle nach wie vor true, das ist ja das Problem. Wenn nicht, würd ich die Methode ja nicht mehr rufen.
Das ist das was er mit "wenn der Zeiger anschtändig nil gesetzt wurde" meinte.

Ich habe mir angewöhnt Objekte immer wie folgt freizugeben:
Delphi-Quellcode:
...
  myObject.Free;
  myObject := nil;
...
Dann funktioniert auch der oben angegebene Code wieder. (asigned prüft auf nil)

Free prüft auch auf nil, deshalb ist folgender Code fehlerhaft:
Delphi-Quellcode:
...
  myObject := TmyObject.Create;
...
  myObject.Free;

  myObject.Free; // hier gibts Exception !!!
...
Folgender code läuft hingegen fehlerfrei:
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:
...
  FreeAndNil(myObject);
...
(ist in SysUtils definiert)
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;
...
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


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 01:51 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