Exception in Konstruktor-Methode auslösen

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Antworten
Kay
Beiträge: 134
Registriert: So 14. Nov 2010, 15:17

Exception in Konstruktor-Methode auslösen

Beitrag von Kay »

Hallo,

mir ist bei der Verwendung von Exceptions ein Effekt aufgefallen, den ich mir nicht erklären kann.

Ich erzeuge ein Objekt und innerhalb der Konstruktor-Methode tritt ein Fehler auf. Ich löse also eine Exception aus und fange diese im Programm ab.
Wenn ich aber nun anschließend die Objektvariable prüfe, dann ist diese nicht nil, obwohl doch kein Objekt erzeugt werden konnte. Womit hängt das denn zusammen? Ist das so gedacht?

Code: Alles auswählen

type
  TPerson = class
  private
    FFirstname: String;
  public
    constructor Create;
    property Firstname: String read FFirstname;
  end;
 
constructor TPerson.Create;
begin
  FFirstname := 'irgendwer';
  raise Exception.Create('test');
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  P: TPerson;
begin
  try
    P := TPerson.Create;
    ShowMessage(P.Firstname);
  except
    on E: Exception do ShowMessage(E.Message);
  end;
 
  if P = nil then
    ShowMessage('P = nil')
  else
    ShowMessage('P <> nil');
end;
Im Prinzip hätte ich ja in diesem Fall gar keine Möglichkeit nachträglich zu prüfen, ob das Objekt überhaupt korrekt erzeugt wurde oder?

Vielen Dank
Zuletzt geändert von Lori am Di 17. Dez 2013, 11:59, insgesamt 1-mal geändert.
Grund: Nutze bitte den richtigen Highlighter! Danke.

Benutzeravatar
theo
Beiträge: 10871
Registriert: Mo 11. Sep 2006, 19:01

Re: Exception in Konstruktor-Methode auslösen

Beitrag von theo »

Bei mir ist es Nil

Lazarus 1.3 r43544M FPC 2.7.1 x86_64-linux-gtk 2

Kay
Beiträge: 134
Registriert: So 14. Nov 2010, 15:17

Re: Exception in Konstruktor-Methode auslösen

Beitrag von Kay »

Das hab ich schon befürchtet. Im Normalfall sollte es ja eigentlich auch nil sein, alles andere wäre mir schleierhaft.
Ich verwende lazarus-1.0.8-fpc-2.6.2-win32. Das scheint wohl fehlerhaft zu sein, Mist!

Yogi72108
Beiträge: 22
Registriert: Fr 10. Feb 2012, 19:09
OS, Lazarus, FPC: Debian wheezy (FPC 2.7.1 SVN 29278; Laz 1.3 SVN 47189)
CPU-Target: 32Bit
Wohnort: im Schwabenländle

Re: Exception in Konstruktor-Methode auslösen

Beitrag von Yogi72108 »

Ich würde das ganz anders angehen:

Code: Alles auswählen

 
type
  TPerson = class
  private
    FFirstname: String;
  public
    constructor Create;
    property Firstname: String read FFirstname;
  end;
 
constructor TPerson.Create;
begin
  FFirstname := 'irgendwer';
  fail;  // Konstruktor abbrechen, aufräumen und nil zurückgeben
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  P: TPerson;
begin
    P := TPerson.Create;
  if Assigned(P)l then
    ShowMessage('P <> nil')
  else
    ShowMessage('P = nil');
end;
 
So kommst du ohne Exception aus

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Exception in Konstruktor-Methode auslösen

Beitrag von m.fuchs »

Ich glaube, dass dieses Verhalten schon so korrekt ist. Der Constructor räumt das erzeugte Objekt wieder auf und es ist nil, ABER: die Zuweisung von P wird ja nicht durchgeführt. Die Exception verhindert das. Also kann P auch nicht nil sein, denn das war es ja vorher nicht.
Wenn du folgendes benutzt:

Code: Alles auswählen

var
  P: TPerson = nil;
funktioniert deine Prüfung auch. P wird dann mit nil initialisiert und alles ist gut.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Exception in Konstruktor-Methode auslösen

Beitrag von m.fuchs »

theo hat geschrieben:Bei mir ist es Nil
Lazarus 1.3 r43544M FPC 2.7.1 x86_64-linux-gtk 2
Exakt mit dem Quellcode des OP?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Benutzeravatar
theo
Beiträge: 10871
Registriert: Mo 11. Sep 2006, 19:01

Re: Exception in Konstruktor-Methode auslösen

Beitrag von theo »

m.fuchs hat geschrieben:
theo hat geschrieben:Bei mir ist es Nil
Lazarus 1.3 r43544M FPC 2.7.1 x86_64-linux-gtk 2
Exakt mit dem Quellcode des OP?
Ja.
Man könnte es auch im Except Block nillen, oder?

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Exception in Konstruktor-Methode auslösen

Beitrag von m.fuchs »

theo hat geschrieben:
m.fuchs hat geschrieben:
theo hat geschrieben:Bei mir ist es Nil
Lazarus 1.3 r43544M FPC 2.7.1 x86_64-linux-gtk 2
Exakt mit dem Quellcode des OP?
Ja.
Wow, dann wurde das ja wirklich geändert. Ich hatte jetzt fest damit gerechnet, dass du (wie ich auch zuerst) den Code etwas abgewandelt hast und P bei dir eine globale Variable ist. Dann wäre sie ja standardmäßig auf nil.
Hmm.
theo hat geschrieben:Man könnte es auch im Except Block nillen, oder?
Aber ja, wobei ich mir inzwischen angewöhnt habe, die Variablen in der Deklaration schon zu initialisieren. Gefällt mir persönlich besser.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Kay
Beiträge: 134
Registriert: So 14. Nov 2010, 15:17

Re: Exception in Konstruktor-Methode auslösen

Beitrag von Kay »

OK, das explizite Setzen auf nil funktioniert sehr gut.

Aber mal interessehalber gefragt: Wenn die Variable nach der Deklaration nicht nil ist, was ist sie dann?
Primitive Datentypen werden ja immer auf einen Standardwert gesetzt, z.B. 0 oder True oder leerer String o.ä. Aber wie ist das bei Objekttypen?

Benutzeravatar
theo
Beiträge: 10871
Registriert: Mo 11. Sep 2006, 19:01

Re: Exception in Konstruktor-Methode auslösen

Beitrag von theo »

Kay hat geschrieben: Primitive Datentypen werden ja immer auf einen Standardwert gesetzt, z.B. 0 oder True oder leerer String o.ä.
Nö, wie kommst du drauf?
http://www.freepascal.org/docs-html/ref/refse22.html

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Exception in Konstruktor-Methode auslösen

Beitrag von m.fuchs »

Kay hat geschrieben:OK, das explizite Setzen auf nil funktioniert sehr gut.
Aber mal interessehalber gefragt: Wenn die Variable nach der Deklaration nicht nil ist, was ist sie dann?
Irgendetwas. Was immer auch vorher in dem entpsrechenden Speicherbereich lag, liegt da weiterhin drin.
Kay hat geschrieben:Primitive Datentypen werden ja immer auf einen Standardwert gesetzt, z.B. 0 oder True oder leerer String o.ä. Aber wie ist das bei Objekttypen?
Nein, werden sie nicht immer. Nur wenn es globale Variablen sind. Lokale Variablen sind nicht initialisiert. Siehe auch folgendes Beispiel:

Code: Alles auswählen

program Project1;
 
{$mode objfpc}
 
uses
  Classes, SysUtils;
 
procedure Local;
var
  i: Integer;
  s: String;
begin
  WriteLn('== Local ==');
  WriteLn(IntToStr(i));
  WriteLn(s);
end;
 
var
  _i: Integer;
  _s: String;
begin
  Local;
  WriteLn('== Global ==');
  WriteLn(IntToStr(_i));
  WriteLn(_s);
  ReadLn;
end.
 
hth
Micha
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Kay
Beiträge: 134
Registriert: So 14. Nov 2010, 15:17

Re: Exception in Konstruktor-Methode auslösen

Beitrag von Kay »

Alles klar, dann experimentiere ich jetzt mal ein bisschen.
Vielen Dank auf jeden Fall für eure Infos!

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Exception in Konstruktor-Methode auslösen

Beitrag von mse »

m.fuchs hat geschrieben:
theo hat geschrieben:
m.fuchs hat geschrieben: Exakt mit dem Quellcode des OP?
Ja.
Wow, dann wurde das ja wirklich geändert. Ich hatte jetzt fest damit gerechnet, dass du (wie ich auch zuerst) den Code etwas abgewandelt hast und P bei dir eine globale Variable ist. Dann wäre sie ja standardmäßig auf nil.
Hmm.
Bei Theo ist die lokale Variable halt zufälligerweise nil. Theos Computer war schon immer etwas ordentlicher als andere. ;-)

Benutzeravatar
theo
Beiträge: 10871
Registriert: Mo 11. Sep 2006, 19:01

Re: Exception in Konstruktor-Methode auslösen

Beitrag von theo »

mse hat geschrieben: Bei Theo ist die lokale Variable halt zufälligerweise nil. Theos Computer war schon immer etwas ordentlicher als andere. ;-)
So isses. Gut erzogen halt. :lol:

Antworten