Fehlerbehandlung:
Wozu ist sie da?
In jedem Programm treten Situationen auf, in denen zur Laufzeit, eine Exception (ein Fehler), auftreten kann. Ein Beispiel dafür ist eine Datei zu öffnen, die nicht existiert oder eine einfache Division durch 0. Um zu vermeiden, dass dadurch das Programm oder sogar das Betriebssystem abstürtzt, kann man, die Stellen im Programm, an denen eine Exception auftreten könnte, in einen
try ... except-Block schreiben (oder in einen
try ... finally-Block, obwohl dieser nicht zur Vermeidung von Exceptions dient).
Beispiel:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| try Memo1.Lines.LoadFromFile(AFileName); except on EFOpenError do HandleFileOpenError;
on EOverFlow do HandleOverFlow;
else end; |
Die Anweisung (es können auch mehrere sein), die hinter
try steht wird ausgeführt. Tritt dabei ein Fehler auf, springt das Programm
direkt in die Exception-Routine (hinter dem Schlüsselwort
except),
ohne dass der weitere Programmtext im
try-Block abgearbeitet wird. Handelt es sich um eine Exception vom Typ
EFOpenError wird die Prozedur
HandleFileOpenError ausgeführt. Diese könnte z.B. so lauten:
Delphi-Quelltext
1: 2: 3: 4:
| procedure TForm1.HandleFileOpenError(); begin; ShowMessage('Datei kann nicht geöffnet werden.'); end; |
Ist die Exception nicht vom Typ
EFOpenError wird die Anweisung hinter dem Schlüsselwort
else ausgeführt.
Wie kann ich eine eigene Exception auslösen?
Um eine eigene Exception auszulösen, muss man natürlich erstmal eine definieren. Eine Exception in Delphi ist nichts anderes als ein Klasse vom Typ
Exception (nicht TException). Eine eigene Exception ist also einfach eine Ableitung der Grundklasse aller Exceptions (es hat sich eingebürgert, dass die Namen aller abgeleiteten Exceptions mit einem E beginnen):
Delphi-Quelltext
1: 2:
| type EMyException = class(Exception); |
Um dann die Exception auszulösen, benutzt man das Schlüsselwort
raise:
Delphi-Quelltext
1: 2:
| if YourPassword <> RightPassword then raise EMyException.Create('Falsches Passwort'); |
Es ist nicht sinnvoll, die eigene Exception in einen
try ... except-Block einzubauen, da man ja die Exception auslösen und nicht deren Auslösung verhindern will.
Wie kann ich Exceptions Global abfangen?
Um alle auftretenden Exceptions abzufangen, um z.B. eine eigene Fehlerbehandlungsroutine zu schreiben, kann man dem
Application.OnException-Event eine Prozedur zuweisen, die bei jeder auftretenden Exception ausgeführt wird (bis auf die, die man vorher abfängt).
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TForm1.OnError(Sender: TObject; E: Exception); begin ShowMessage(E.Message); end;
procedure TForm1.FormCreate(Sender: Tobject); begin Application.OnException := OnError; end; |
Wie kann ich verhindern, das eine Fehlermeldung erscheint?
Delphi-Quelltext
1: 2: 3: 4: 5:
| try ... except Abort; end; |
Wie kann ich eine Exception erneut auslösen?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| try Memo1.Lines.LoadFromFile(AFileName); except on EFOpenError do HandleFileOpenError; Raise; end; |
Der try ... finally-Block:
Der
finally-Block enthält Anweisungen, die auf jeden Fall ausgeführt werden (auch bei Auftreten einer Exception). Sie werden auch ausgeführt, sollte innerhalb des
try-Blockes die Standardprozeduren
exit oder
break aufgerufen werden.
Zur Grundlage dieses FAQs diente mir das Buch Nitty Gritty Delphi 6 von Frank Eller.
O'rallY