Finally-Blöcke erstellen
Nach oben zu Geschützte Blöcke definieren
Eine Exception-Behandlungsroutine besteht aus Quelltext, der eine bestimmte Exception oder die in einem geschützten Quelltextblock auftretenden Exceptions verarbeitet. Es kann jedoch vorkommen, dass eine Exception nicht behandelt werden muss, aber bestimmte Anweisungen nach dem geschützten Block auch dann ausgeführt werden sollen, wenn eine Exception ausgelöst wird. Für gewöhnlich handelt es sich dabei um Bereinigungsarbeiten, wie z. B. die Freigabe von Ressourcen, die vor dem geschützten Block reserviert wurden.
Durch die Verwendung von finally-Blöcken können Sie sicherstellen, dass von der Anwendung reservierte Ressourcen auch dann freigegeben werden, wenn eine Exception ausgelöst wird. Weist die Anwendung beispielsweise Speicher zu, müssen Sie sicherstellen, dass dieser Speicher auch wieder freigegeben wird. Wird eine Datei geöffnet, muss sie später auch wieder geschlossen werden. Unter normalen Umständen können Sie die Freigabe zugewiesener Ressourcen durch eine Anwendung gewährleisten, indem Sie Quelltext zur Zuweisung und zur Freigabe dieser Ressourcen schreiben. Sie müssen jedoch sicherstellen, dass der Code zur Freigabe der Ressourcen auch ausgeführt wird, nachdem eine Exception aufgetreten ist.
Insbesondere die folgenden Ressourcen müssen immer freigegeben werden:
- Dateien
- Arbeitsspeicher
- Windows-Ressourcen oder Widget-Bibliotheksressourcen (Qt-Objekte)
- Objekte (Instanzen von Klassen in Ihrer Anwendung)
Die folgende Ereignisbehandlungsroutine zeigt, wie eine Exception verhindern kann, dass eine Anwendung den von ihr reservierten Speicher freigibt:
procedure TForm1.Button1Click(Sender: TObject);
var
APointer: Pointer;
AnInteger, ADividend: Integer;
begin
ADividend := 0;
GetMem(APointer, 1024);{ allocate 1K of memory }
AnInteger := 10 div ADividend;{ this generates an exception }
FreeMem(APointer, 1024);{ this never gets called because of the exception}
end;
Obwohl die meisten Fehler nicht so offensichtlich sind, veranschaulicht dieses Beispiel einen wichtigen Punkt: Wenn eine Exception auftritt, wird die Ausführung außerhalb des Blocks fortgesetzt, sodass die Anweisung zur Freigabe des Speichers nie aufgerufen wird.
Um sicherzustellen, dass der Speicher freigegeben wird, können Sie einen try-Block zusammen mit einem finally-Block verwenden.
Erstellen eines "finally"-Blocks
Finally-Blöcke werden durch das Schlüsselwort finally eingeleitet. Sie sind Teil einer try...finally-Anweisung, die folgende Form hat:
try { statements that may raise an exception} finally { statements that are called even if there is an exception in the try block} end;
Die Anwendung führt bei einer try...finally-Anweisung stets die im finally-Abschnitt enthaltenen Anweisungen aus, auch wenn im try-Block eine Exception ausgelöst wird. Löst eine Anweisung oder Routine im try-Block (oder eine Routine, die von dem im try-Block enthaltenen Code aufgerufen wird) eine Exception aus, wird die Ausführung an diesem Punkt unterbrochen. Sobald eine Exception-Behandlungsroutine gefunden wird, setzt die Anwendung die Ausführung im finally-Abschnitt fort. Dieser Abschnitt wird auch als Bereinigungscode bezeichnet. Nachdem der finally-Abschnitt verarbeitet wurde, wird die Exception-Behandlungsroutine aufgerufen. Tritt keine Exception auf, wird der Bereinigungscode in der angegebenen Reihenfolge ausgeführt, also nach den Anweisungen im try-Block.
Das folgende Codefragment zeigt eine Ereignisbehandlungsroutine, die mithilfe eines finally-Blocks sicherstellt, dass der zugewiesene Speicher auch dann freigegeben wird, wenn ein Fehler generiert wird:
procedure TForm1.Button1Click(Sender: TObject); var APointer: Pointer; AnInteger, ADividend: Integer; begin ADividend := 0; GetMem(APointer, 1024);{ allocate 1K of memory } try AnInteger := 10 div ADividend;{ this generates an exception } finally FreeMem(APointer, 1024);{ execution resumes here, despite the exception } end; end;
Die Anweisungen im finally-Block sind nicht vom Auftreten einer Exception abhängig. Wenn keine der Anweisungen im try-Abschnitt eine Exception auslöst, wird der finally-Block ausgeführt.