Feststellen ob ein Object gelöscht wurde

Hallo,
wie kann ich feststellen ob ein bestimmtes Object bereits gelöscht wurde?

Beispiel:
Das Object wird angelegt mit
obj:=TButton.Create(Form1);
wenn nun das Formular Form1 gelöscht wird, wird automatisch auch der Button gelöscht.

Wie kann ich festellen ob der Button noch existiert oder ob er bereits freigegeben wurde?

Vielen Dank
Joachim

Hallo Joachim,

mit der Abfrage

if Assigned(obj) then
 // Object existiert noch

Gruß Mike

Hallo,

mit der Abfrage

if Assigned(obj) then
// Object existiert noch

das stimmt so nicht.
assigned prüft nicht, ob das Objekt noch existiert, sondern ob die Objektvariable nil ist. Führ einmal folgenden Code aus:

var
 B: TButton;

procedure TForm1.Button1Click(Sender: TObject);
begin
 Form2 := TForm2.Create(nil);
 B := TButton.Create(Form2);
 B.Parent := Form2;
 B.Top := 10;
 B.Left := 10;
 Form2.ShowModal;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 Form2.Free;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
 if Assigned(B)then ShowMessage('ist assigned') 
 else ShowMessage('ist not assigned');
end;

Nun klicke der Reihe nach

  • Button1 (Form erzeugen, ButtonVariable zuweisen und Form 1mal zeigen)
  • Button2 (Form zerstören)
  • Button3 (Zuweisung prüfen)

hier bleibt B immer noch „assigned“.
Aus diesem Grund ist es auch gute Praxis, nach dem Zerstören eines Objekts die Objektvariable auf nil zu setzen.

Ich würde im vorliegenden Fall ganz normal in einem try-except-Block über die Variable auf das Objekt zugreifen und bei Auslösen der Exception vom Typ EAccessViolation die Variable auf nil setzen.

procedure TForm1.Button3Click(Sender: TObject);
begin
 if Assigned(B)then ShowMessage('ist assigned') else ShowMessage('ist not assigned');

 try
 B.Top := 20;
 except
 on e: EAccessViolation do B := nil;
 end;
end;

wird jetzt der Button3 gedrückt (nach Button1 und 2), so erscheint zunächst „is assigned“. Dann wird die Exception ausgelöst und bei einem weiteren Druck auf Button3 ist es dann „is not assigned“. Dafür sind Exception-Schutzblöcke da.

Gruss, Niels

Hallo,

probier einen Zugriff auf ein Feld des Objekts. Wenn das Objekt nicht mehr existiert, gibt es eine Zugriffsverletzung. Damit die nicht zum Programmabbruch führt, machst Du das in einem try-except-Block:

function ObjExists(Obj:TObject):Boolean;
begin
 try
 result := (Obj.ClassName "Ö")
 except
 on exception do result := FALSE
 end;
end;

Gruß,
Jochen

Hallo Jochen

probier einen Zugriff auf ein Feld des Objekts. Wenn das
Objekt nicht mehr existiert, gibt es eine Zugriffsverletzung.

Auf die Idee mit dem Try-Except Block bin ich auch schon gekommen, ich dachte nur es gibt vielleicht auch eine „saubere“ Lösung.

Vielen Dank, Joachim

Hallo,

Auf die Idee mit dem Try-Except Block bin ich auch schon
gekommen, ich dachte nur es gibt vielleicht auch eine
„saubere“ Lösung.

der Try-Except-Block ist die saubere Lösung. Nur dadurch hast du die Garantie, alle auftretenden Exceptions abzufangen. Die Alternative wäre je nach Programm massenweise if-Abfragen einzufügen, durch die der Code zerstückelt wird. Auch nicht gerade elegant, oder? Try-Except macht es möglich, die Fehlerbehandlung vom laufenden Code zu trennen, wodurch das Programm insgesamt übersichtlicher wird (wenn man’s richtig macht).

Gruss, Niels

Hallo Niels

der Try-Except-Block ist die saubere Lösung

Das Problem bei dieser Lösung ist, dass bei eingeschaltetem Debugger immer an dieser Stelle eine lästige Fehlermeldung kommt.

Ich habe übrigens unter http://www.delphipraxis.net/topic17825_isobject+iscl… eine interessante Diskusion zu diesem Thema gefunden.
Viele Grüße, Jochim Knöll

Hallo,

der Try-Except-Block ist die saubere Lösung

Das Problem bei dieser Lösung ist, dass bei eingeschaltetem
Debugger immer an dieser Stelle eine lästige Fehlermeldung
kommt.

Unter Tools, Debugger-Optionen, BS-Exceptions unten
Integrierte Fehlersuche deaktivieren!

Es lassen sich auch einzelne Exceptions aus der integrierten Fehlersuche rausnehmen.

Ich habe übrigens unter
http://www.delphipraxis.net/topic17825_isobject+iscl…
eine interessante Diskusion zu diesem Thema gefunden.

Wow, ich hätte nicht gedacht, daß das Problem sooo schwierig ist. Wie dem auch sei, ich favorisiere und empfehle, in der Programmstruktur logisch sicherzustellen, daß

  1. Referenzen auf freigegebene Objekte IMMER auf NIL gesetzt werden
  2. Objekte mit noch aktiven abhängigen Referenzen NICHT freigegeben werden

Dabei kann es u.U. nötig sein, Daten/Objekte besser zu kapseln und ggf. an Kopien zu arbeiten.

Viele Grüße, Jochen

Hallo Joachim,

der Try-Except-Block ist die saubere Lösung

Das Problem bei dieser Lösung ist, dass bei eingeschaltetem
Debugger immer an dieser Stelle eine lästige Fehlermeldung
kommt.

dann schalte diese Funktion doch einfach ab:

Menu: Tools -> Debugger-Optionen
dort den Reiter „BS-Exceptions“ wählen und „behandelt von“ auf „Anwenderprogramm“ stellen.

Gruß, Niels

Hallo

Falsch - es muss heißen…

 if Assigned(Object) and (Object nil) then
 bAssigned := true
 else
 bAssigned := false;

Gruß

Hallo,

Falsch - es muss heißen…

if Assigned(Object) and (Object nil) then
bAssigned := true
else
bAssigned := false;

also zum Einen: wo muss es das heißen? Ich finde keine Stelle, an der dieser Code passen würde.

und zum Anderen:
wie oben bereits erwähnt, prüft die Funktion assigned(Obj) ob das Object nil ist. Dein Code heißt also im Prinzip:

if (Object nil) and (Object nil) then

Das scheint mir aber irgendwie nicht sehr intelligent…

Gruss, Niels