Behandlung von Ausnahmen in der Delphi-Ausnahmebehandlung

Hier ist eine interessante Tatsache: Kein Code ist fehlerfrei - tatsächlich ist ein Teil des Codes absichtlich voller "Fehler".

Was ist ein Fehler in einer Anwendung? Ein Fehler ist eine falsch codierte Lösung für ein Problem. Dies sind logische Fehler, die zu falschen Funktionsergebnissen führen können, wenn alles gut zusammen passt, das Ergebnis der Anwendung jedoch völlig unbrauchbar ist. Bei logischen Fehlern funktioniert eine Anwendung möglicherweise nicht mehr.

Ausnahmen können Fehler in Ihrem Code enthalten, wenn Sie versuchen, Zahlen durch Null zu teilen, oder wenn Sie versuchen, freigegebene Speicherblöcke zu verwenden oder falsche Parameter für eine Funktion anzugeben. Eine Ausnahme in einer Anwendung ist jedoch nicht immer ein Fehler.

Ausnahmen und die Ausnahmeklasse

Ausnahme sind Sonderbedingungen, die eine besondere Behandlung erfordern. Wenn eine Fehlerart auftritt, löst das Programm eine Ausnahme aus.

Sie (als Anwendungsentwickler) werden Ausnahmen behandeln, um Ihre Anwendung fehleranfälliger zu machen und auf die Ausnahmebedingung zu reagieren.

In den meisten Fällen sind Sie sowohl der Anwendungsautor als auch der Bibliotheksautor. Sie müssen also wissen, wie Sie Ausnahmen (aus Ihrer Bibliothek) auslösen und wie Sie damit umgehen (aus Ihrer Anwendung)..

Der Artikel zur Behandlung von Fehlern und Ausnahmen enthält einige grundlegende Richtlinien zum Schutz vor Fehlern mit try / except / end- und try / finally / end-geschützten Blöcken, um auf außergewöhnliche Bedingungen zu reagieren oder diese zu behandeln.

Ein einfacher Versuch mit Ausnahme von Schutzblöcken sieht folgendermaßen aus:


Versuchen
ThisFunctionMightRaiseAnException ();
außer// Hier werden alle in ThisFunctionMightRaiseAnException () ausgelösten Ausnahmen behandelt
Ende;

Die ThisFunctionMightRaiseAnException enthält in ihrer Implementierung möglicherweise eine Codezeile wie


erziehen Exception.Create ('besondere Bedingung!');

Die Ausnahme ist eine spezielle Klasse (eine von wenigen ohne ein T vor dem Namen), die in der Einheit sysutils.pas definiert ist. Die SysUtils - Einheit definiert mehrere spezielle Exception - Nachkommen (und erstellt somit eine Hierarchie von Exception - Klassen) wie ERangeError, EDivByZero, EIntOverflow usw.

In den meisten Fällen gehören die Ausnahmen, die Sie im protected try / except-Block behandeln würden, nicht zur Exception-Klasse (Basisklasse), sondern zu einer speziellen Exception-Nachkommenklasse, die entweder in der VCL oder in der von Ihnen verwendeten Bibliothek definiert ist.

Ausnahmen mit Try / Except behandeln

Um einen Ausnahmetyp abzufangen und zu behandeln, würden Sie einen Ausnahmehandler "on type_of_exception do" erstellen. Das "on exception do" ähnelt in etwa der klassischen case-Anweisung:


Versuchen
ThisFunctionMightRaiseAnException;
Ausgenommen EZeroDivide Dobegin// Etwas beim Teilen durch NullEnde;
auf EIntOverflow Dobegin// Etwas bei zu großer GanzzahlberechnungEnde;
sonst fange an// Etwas, wenn andere Ausnahmetypen ausgelöst werdenEnde;
Ende;

Beachten Sie, dass der else-Teil alle (anderen) Ausnahmen erfasst, einschließlich derjenigen, von denen Sie nichts wissen. Im Allgemeinen sollte Ihr Code nur Ausnahmen behandeln, von denen Sie wissen, wie sie zu behandeln sind, und von denen Sie erwarten, dass sie ausgelöst werden.

Außerdem sollten Sie niemals eine Ausnahme "essen":


Versuchen
ThisFunctionMightRaiseAnException;
außer
Ende;

Wenn Sie die Ausnahme essen, wissen Sie nicht, wie Sie mit der Ausnahme umgehen sollen, oder Sie möchten nicht, dass Benutzer die Ausnahme oder etwas dazwischen sehen.

Wenn Sie die Ausnahme behandeln und mehr Daten von ihr benötigen (es ist schließlich eine Instanz einer Klasse), können Sie nur den Typ der Ausnahme ausführen:


Versuchen
ThisFunctionMightRaiseAnException;
Ausgenommen E: Ausnahme Dobegin
ShowMessage (E.Message);
Ende;
Ende;

Das "E" in "E: Exception" ist eine temporäre Exception-Variable des Typs, der nach dem Spaltenzeichen angegeben ist (im obigen Beispiel die Basis-Exception-Klasse). Mit E können Sie Werte in das Ausnahmeobjekt lesen (oder schreiben), z. B. die Message-Eigenschaft abrufen oder festlegen.

Wer macht die Ausnahme frei??

Ist Ihnen aufgefallen, dass Ausnahmen tatsächlich Instanzen einer von Exception abgeleiteten Klasse sind? Das Schlüsselwort raise löst eine Instanz einer Ausnahmeklasse aus. Was Sie erstellen (die Ausnahmeinstanz ist ein Objekt), müssen Sie ebenfalls freigeben. Wenn Sie (als Bibliotheksschreiber) eine Instanz erstellen, gibt der Anwendungsbenutzer sie frei?

Hier ist die Delphi-Magie: Die Behandlung einer Ausnahme zerstört das Ausnahmeobjekt automatisch. Das heißt, wenn Sie den Code in den Block "except / end" schreiben, wird der Ausnahmespeicher freigegeben.

Was passiert also, wenn ThisFunctionMightRaiseAnException tatsächlich eine Ausnahme auslöst und Sie diese nicht verarbeiten (dies ist nicht dasselbe wie "essen")??

Was ist, wenn Number / 0 nicht verarbeitet wird??

Wenn in Ihrem Code eine nicht behandelte Ausnahme ausgelöst wird, behandelt Delphi Ihre Ausnahme erneut auf magische Weise, indem es dem Benutzer das Fehlerdialogfeld anzeigt. In den meisten Fällen werden in diesem Dialogfeld nicht genügend Daten bereitgestellt, damit der Benutzer (und schließlich Sie) die Ursache der Ausnahme verstehen kann.

Dies wird durch die Nachrichtenschleife der obersten Ebene von Delphi gesteuert alle Ausnahmen werden vom globalen Anwendungsobjekt und seiner HandleException-Methode verarbeitet.

Um Ausnahmen global zu behandeln und Ihren eigenen benutzerfreundlicheren Dialog anzuzeigen, können Sie Code für die Ereignisbehandlungsroutine TApplicationEvents.OnException schreiben.

Beachten Sie, dass das globale Anwendungsobjekt in der Formulareinheit definiert ist. TApplicationEvents ist eine Komponente, mit der Sie die Ereignisse des globalen Anwendungsobjekts abfangen können.