AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi Der Konstruktor ist abgestürzt - Wie gehe ich im Destruktor am besten vor?
Thema durchsuchen
Ansicht
Themen-Optionen

Der Konstruktor ist abgestürzt - Wie gehe ich im Destruktor am besten vor?

Ein Thema von Der schöne Günther · begonnen am 11. Apr 2013 · letzter Beitrag vom 12. Apr 2013
Antwort Antwort
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.662 Beiträge
 
Delphi 12 Athens
 
#1

AW: Der Konstruktor ist abgestürzt - Wie gehe ich im Destruktor am besten vor?

  Alt 11. Apr 2013, 14:35
Davon ausgehend, dass es sich bei den angesprochenen Objekten um private Felder der eigenen Klasse handelt, musst Du nichts weiter beachten. Diese sind initial nil, wenn Du sie also im Destruktor mit Free freigibst, passiert nichts, da Free erst auf nil prüft und dann erst Destroy aufruft. Daraus folgt: was nicht da ist, wird auch nicht versucht freizugeben.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.201 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: Der Konstruktor ist abgestürzt - Wie gehe ich im Destruktor am besten vor?

  Alt 11. Apr 2013, 14:42
Tatsächlich. Ich bin durcheinandergekommen da der Debugger bei einer Exception im Konstruktor einen mit F7 nicht mehr durch den Destruktor wandern lässt soweit man nicht explizit einen Haltepunkt dort hineinsetzt.

Ich rede wirres Zeug, belassen wir es damit
  Mit Zitat antworten Zitat
Benutzerbild von ConnorMcLeod
ConnorMcLeod

Registriert seit: 13. Okt 2010
Ort: Bayern
490 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Der Konstruktor ist abgestürzt - Wie gehe ich im Destruktor am besten vor?

  Alt 11. Apr 2013, 15:50
Vllt bin ich jetzt auf dem falschen Dampfer, aber was spricht gegen FreeAndNil ?
Nr.1 Delphi-Tool: [F7]
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.662 Beiträge
 
Delphi 12 Athens
 
#4

AW: Der Konstruktor ist abgestürzt - Wie gehe ich im Destruktor am besten vor?

  Alt 11. Apr 2013, 15:57
Im Prinzip nichts, aber Free genügt in diesem Falle auch.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.784 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: Der Konstruktor ist abgestürzt - Wie gehe ich im Destruktor am besten vor?

  Alt 11. Apr 2013, 16:03
.. freeAndNil erzeugt eine Exception wenn die freizugebene Instanz nicht mehr existiert.

Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
flipdascript

Registriert seit: 20. Mai 2008
25 Beiträge
 
Delphi 2010 Professional
 
#6

AW: Der Konstruktor ist abgestürzt - Wie gehe ich im Destruktor am besten vor?

  Alt 11. Apr 2013, 16:07
.. freeAndNil erzeugt eine Exception wenn die freizugebene Instanz nicht mehr existiert.

Grüße
Klaus
Aber nur, wenn die Referenz <> nil ist. Das ist keine Einschränkung von FreeAndNil. In dem Fall würde es bei Referenz.Free genauso knallen.
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#7

AW: Der Konstruktor ist abgestürzt - Wie gehe ich im Destruktor am besten vor?

  Alt 11. Apr 2013, 16:35
Delphi-Quellcode:
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TMyBuggyObject = class
    PrivObject1: TObject;
    PrivObject2: TObject;
    constructor Create;
    destructor Destroy; override;
  end;

constructor TMyBuggyObject.Create;
begin
  Writeln('TMyBuggyObject.Create(): Allocating object1');
  PrivObject1 := TObject.Create;
  Writeln('TMyBuggyObject.Create(): Throwing exception');
  raise Exception.Create('TMyBuggyObject.Constructor - selfdestruct');
  Writeln('TMyBuggyObject.Create(): Allocating object2');
  PrivObject2 := TObject.Create;
end;

destructor TMyBuggyObject.Destroy;
begin
  Writeln('TMyBuggyObject.Destroy(): Im being called.');
  Writeln('TMyBuggyObject.Destroy(): PrivObj1=0x' + IntToHex(integer(PrivObject1), 8));
  Writeln('TMyBuggyObject.Destroy(): PrivObj2=0x' + IntToHex(integer(PrivObject2), 8));
  Writeln('TMyBuggyObject.Destroy(): Freeing both!');
  PrivObject2.Free;
  PrivObject1.Free;
  inherited;
end;

procedure main;
var
  Instance: TMyBuggyObject;
begin
  Instance := NIL;
  try
    Instance := TMyBuggyObject.Create;
    try
      Writeln('Maincode: No exception!');
    finally
      Instance.Free;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Writeln('Address of instance:'#9'0x', IntToHex(integer(Instance), 8));
  Readln;
end;

begin
  ReportMemoryLeaksOnShutdown := True;
  main;
end.
Code:
TMyBuggyObject.Create(): Allocating object1
TMyBuggyObject.Create(): Throwing exception
TMyBuggyObject.Destroy(): Im being called.
TMyBuggyObject.Destroy(): PrivObj1=0x00520D10
TMyBuggyObject.Destroy(): PrivObj2=0x00000000
TMyBuggyObject.Destroy(): Freeing both!
Exception: TMyBuggyObject.Constructor - selfdestruct
Address of instance:   0x00000000
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#8

AW: Der Konstruktor ist abgestürzt - Wie gehe ich im Destruktor am besten vor?

  Alt 11. Apr 2013, 16:59
Also generell sollte man einen Konstruktor so schreiben das er keine Exception auslösen kann!!!
Das heisst also keine Resouren (mit Ausnahme von Speicher) belegen, keine Dateioperationen, keine problematischen Windows-API-Aufrufe, usw.

Die Folge ist aber, dass man dann evtl. ein unvollständig initialisiertes Objekt erhält.
Diesen Zustand kann man aber dadurch abhelfen, dass man eine Setup-Methode hat, die das Objekt vollständig initialisiert:
Delphi-Quellcode:
var
  meinobj : TMyClass;
begin
  meinobj := TMyClass.Create;
  try
    meinobj.Setup;
    mainobj.MachwasDamit;
  finally
    meinobj.Free;
  end;
Dies hat aber den unschönen Effekt, dass man mehr Schreibarbeit hat und dass man den Aufruf von Setup auch mal vergessen kann.
Dem kann aber abgeholfen werden, indem man die Setup-Methode so schreibt:
Delphi-Quellcode:
type
  TMyClass=class(TObject)
  private
    FSetupDone : Boolean;
  protected
    procedure Setup;virtual;
  public
    procedure MachWasDamit;
  end;

procedure TMyClass.Setup;
begin
  if not FSetupDone then
  begin
    // hier der Code der nicht in den Konstruktor soll, weil er potentiell eine Exception
    // auslösen kann
    ...
    FSetupDone := True;
  end;
end;

procedure TMyClass.MachWasDamit;
begin
  Setup; // wird jeder Methode von TMyClass aufgerufen, damit sichergestellt wird
  // dass das Objekt vollständig initialisert ist

  // hier der Code von MachWasDamit
  ..
end;
Ok, diese Methode bedeutet mehr Schreibarbeit und auch eine minimale Performanceverschlechterung aber man vermeidet so eine Exception im Konstruktor mit allen seinen hässlichen Konsequenzen.

Es gibt auch noch andere Möglichkeiten um Code im Konstruktor zu vermeiden, der potentiell eine Exception auslösen kann.
Stichwort: Dependeny Injection

Angenommen ein Thread soll in eine Datei loggen.
Im naiven Ansatz würde man das so machen:
Delphi-Quellcode:
constructor TMyThread.Create;
begin
  inherited Create;
  FLogger := TLogger.Create;
  // Gefahr!
  // hier kann eine Exception ausgelöst werden (z.B. keine Schreibrechte auf der Lodatei)
  FLogger.OpenLogfile('C:\log.txt');
end;
Bei der Dependency Injection würde die Threadklasse verlangen, dass ein geöffnetes (!) Logobjekt übergeben wird:
Delphi-Quellcode:
constructor TMyThread.Create(logger:TLogger);
begin
  inherited Create;
  FLogger := logger; // das ist sicher; keine Exception möglich
end;
  Mit Zitat antworten Zitat
Antwort Antwort

 

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 23:43 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