Zunächst, Dein erstes Posting: Wenn der Aufruf von
TTypMeinerObjektVariablen.Create; fehlschlägt, wird implizit der Destruktor für dieses Exemplar aufgerufen.
Der Code
Delphi-Quellcode:
try
myVar:= TMyClass.Create;
finally
myVar.Free;
end;
kann daher bei lokalen Variablen zu fehlern führen, weil
myVar bei einer
Exception im Konstruktor nie beschrieben wird und die Nachricht
Free deshalb an eine nicht-initialisierte Referenz geschickt (die Methode aufgerufen) wird.
Reicht der implizite Aufruf des Destruktors nicht aus? Warum möchtest Du den Fall, dass der Constructor eine
Exception wirft, abfangen? Wie willst Du reagieren, wenn der Destruktor, zB wg nur teilweise erzeugten aggregierten Objekten, seinerseits beim impliziten Aufruf eine
Exception wirft? Mit dem Code
Delphi-Quellcode:
type
TMyClass =
class
public
constructor Create;
destructor Destroy;
override;
end;
constructor TMyClass.Create;
begin
inherited Create;
raise Exception.Create('
exception within a constructor');
end;
destructor TMyClass.Destroy;
begin
raise Exception.Create('
exception within a destructor');
inherited;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
myVar: TMyClass;
begin
myVar:= TMyClass($badf00d);
//stack contains rubbish
try
myVar:= TMyClass.Create;
try
finally
myVar.Free;
end;
except
on E:
Exception do
outputDebugString(PChar('
Exception:'+E.
Message));
end;
end;
kannst Du diesen Fall gut simulieren und erkennen, dass die ursprüngliche
Exception "verschluckt" wird.
Mit
GetHeapStatus.TotalAllocated kannst Du Dich vergewissern, dass in diesem trivialen Bsp der gesamt Speicher durch den impliziten Aufruf freigegeben wird.
Trotzdem: Durch ein simples Abfangen einer
Exception, die vom Konstruktor geworfen wird, ist Dir bei aggregierten Objekten nicht geholfen, wenn der Destruktor mit einer
Exception, die vom Konstruktor geworfen wird, nicht umgehen kann.