Object Pascal
Objekte freigeben: Destruktor
Wird eine Instanz einer Klasse nicht mehr benötigt, sollte der dafür verwendete Hauptspeicher wieder freigegeben werden. Dies geschieht mit dem Gegenstück zum Konstruktor, dem Destruktor ("Zerstörer"). Destroy heißt dieser bei von TObject abgeleiteten Klassen. Um ein Objekt freizugeben, sollte jedoch die Methode Free verwendet werden. Free prüft, ob ein Verweis auf nil vorliegt, anschließend wird Destroy aufgerufen. Die Objektreferenz verweist jetzt allerdings nicht unbedingt auf nil. Soll das der Fall sein, kann auf die Prozedur FreeAndNil (Unit SysUtils) zurückgegriffen werden, die das freizugebende Objekt als Parameter erwartet - es handelt sich hier nicht um eine Methode.
Unter .NET arbeitet im Hintergrund ein Garbage Collector - eine Art Müllsammler, der alle nicht mehr benötigten Speicherbereiche ermittelt und frei gibt. Wann das genau ist, kann man nicht festlegen. Vorteil für den Programmierer: Er kann nicht mehr vergessen, selbst erstellte Objekte wieder freizugeben und damit Speicherlöcher zu produzieren. Stattdessen kümmert sich die .NET-Laufzeitumgebung (CLR) darum.
Dennoch sollte der Aufruf von free erfolgen, um andere Ressourcen freizugeben. Der Garbage Collector kümmert sich nur um den Speicher.
Wie beim Konstruktor unterscheidet sich Delphi auch hier von C++. Bei Delphi kümmert sich der Destruktor um die Speicherfreigabe. Damit es möglich ist den Vorfahrdestruktor aufzurufen, wird hier, wie beim Konstruktor, ein zweiter versteckter Aufrufmodus-Parameter im DH CPU-Register übergeben. Der Destruktor kennt im Vergleich zum Konstruktor jedoch nur zwei Aufrufmodi.
Der erste Modus ist Destruction with Deallocation, bei dem DH den Wert 1 enthält. Dieser wird beim direkten Aufruf des Destruktors benutzt und führt zum Aufruf von BeforeDestruction gefolgt von einem _ClassDestroy. Dieses gibt das Objekt mittels FreeInstance frei. FreeInstance seinerseits ruft vor dem Freigeben die Methode CleanupInstance auf, um alle referenzgezählten Felder (String, dyn. Array, Interface) ordnungsgemäß aufzuräumen.
Der zweite Aufrufmodus ist Inherited Destruction, bei dem DH den Wert 0 enthält. Er findet beim Aufruf des Vorfahrdestruktor mittels inherited Verwendung. Hierbei wird der _ClassDestroy Aufruf übersprungen und somit wird das Objekt nicht vorzeitig freigegeben. Wie oben bereits erwähnt, wird der Destruktor automatisch aufgerufen, wenn im Konstruktor eine Exception auftritt. Aus diesem Grund sollte man beim Erzeugen einer Instanz den try/finally-Block wie folgt schreiben.
Reference := TMyClass.Create;
try
...
finally
Reference.Free;
end;
Die Schreibweise, bei der das try vor dem Konstruktor-Aufruf steht, führt bei einer Exception im Konstruktor zu einer zusätzlichen Schutzverletzung, da Reference.Free dann auch aufgerufen wird, wenn in Reference ein undefinierter Wert steht.