set margins 1 40
(mit c-t in Kommandozeile)

Artikel Fehlerbehandlung in Forth
clv01mar88


Kurzfassung: Ausgehend von einer Analyse
des Bedrfnisses nach
programmspezifische Fehlerbehandlung
(die insbesondere zum erweiterten
Begriff des 'Exception handling' fhrt)
werden Konzepte aus verschiedenen Programmiersprachen
und bisher zu Forth83 vorgeschlagene
FORML-Konferenzen auf ihre Brauchbarkeit
hin diskutiert. Es folgt eine unter
ultraFORTH83 rev 3.8 auf einem C16
entwickelte
L”sung des Autors, die abh„ngig von
der Ausfhrungsebene eine spezielle
mittels FAILS..THEN installierte
Behandlung der Worte ABORT" und ERROR"
gestattet.

Stichworte: Fehlerbehandlung,
Exzeption-Handling, Returnstack

1) ABORT" und ERROR"

Im 83er-Standard ist das zentrale Wort
zur Fehlerbehandlung ABORT". Es
gibt den folgenden String als
Fehlernachricht aus, versetzt das System
in einen (einigermaáen) definierten
Zustand und ruft das Top-Level-Wort QUIT
auf, das Eingaben von der Tastatur
entgegennimmt und verarbeitet.
Jedes laufende Programm wird also ohne
Rcksicht auf Verluste gestoppt und
gewissermaáen Forth neu gestartet.

Eine „hnliche Wirkung haben die Worte
ABORT, ERROR" und QUIT selbst.

2.) Diese Art der Fehlerbehandlung
funktioniert zwar meistens recht gut,
wirft aber einige Probleme auf.
Im folgenden wird versucht,
Anforderungen an eine problemspezifische
Fehlerbehandlung zu formulieren:
    - Reservierte  Ressourcen
      schlieáen
    - Informationen ber den
      Fehlerzustand erhalten.
    - Behandlung von Ausnahmesituationen
      bersichtlich programmieren
    - Fehler auch w„hrend der
      Fehlerbehandlung (ohne
      Endlosschleifen)

 Falls das Programm gewisse
Ressourcen
reserviert hat, werden sie nicht wieder
frei gegeben. Dies k”nnte ein ge”ffnetes
File sein, das nicht geschlossen wird;
ein Semaphor, das gelockt bleibt; ein
menartiger Bildschirm, der weiter in
allen Farben des Spektrums blinkt; eine
hoffnungslos verdrehte Schnittstelle
etc.. Am auff„lligsten ist eine z.B. auf
den Drucker umgeleitete Standardausgabe.
In diesem Fall wird schon die Ausgabe
der ABORT"-Meldung (auf den Drucker)
fehlschlagen, insb. wenn die gewnschte
Fehlermeldung "Drucker ausgeschaltet"
heiáen mag. Dieser Effekt wird in jedem
intelligenten Forth-System natrlich
abgefangen, unter MS-DOS l„át er
sich allerdings noch sehr hbsch
beobachten. Die gelockten Semaphore
machen sich allerdings - in seltenen
F„llen - auch unter volksFORTH
bemerkbar. V”llig hoffnungslos wird der
Fall, wenn eine gr”áere
Stand-Alone-Anwendung (z.B. ein
frchterlich kompliziertes Menprogramm)
grade s„mtliche Systemvektoren
erfolgreich verbogen hat und nun durch
einem j„mmerlich kleinen Fehler
(vielleicht einen offengelassener
Diskettenschacht) j„h in die
Forth-Hauptschleife geschleudert wird.
In einem Fall wie letzterem w„re es
sogar denkbar,
den Fehler noch in der Systemroutinem
zu beseitigen
(z.B. den Benutzer aufzufordern doch
bitte den Schacht zu schlieáen) und
anschlieáend fortzufahren, ohne daá
das darberliegende Programm etwas
bemerkt. Derartiges kann sogar das
pr„historische MS-DOS. Alle Fehler die
in Zusammenhang mit Diskettenlaufwerkern
stehen werden noch innerhalb des
Betriebssystems mit einer Meldung der
Form:

allgemeiner Fehler. Kaffee in Laufwerk A:
(A)bbruch, (W)iederholen, (I)gnorieren ?

beantwortet. Der Benutzer kann sich nun
fr eine der Alternativen entscheiden.
Tippt er 'W', so versucht das System
denselben Zugriff nochmal. Dies ist bei
einem offen gelassenen Schacht ntzlich,
gegen Kaffee hilft es natrlich nicht.
'A' terminiert das laufende Programm und
springt zurck ins Betriebssystem (in
etwa wie unser QUIT). Dies funktioniert
meistens, es sei denn das Betriebssystem
m”chte selbst Teile seiner selbst von
der Diskette lesen: Wir bekommen die
beliebte Endlosschleife, bis wir eine
saubere Diskette eingelegt haben.
Die Alternative 'I' ist die hbscheste.
Das System vergiát die Operation und
kehrt ins rufende Programm zurck.
Dieses arbeitet brav weiter, bis es an
sich an irgendwelchenden Zufallsergebnissen
den Magen verdirbt.

Ein anderes hbsches Beispiel
fr sinnvolle Fehler-Behandlung k”nnte
die Behandlung eines File-Ende-Fehlers
sein. Ein Programm lese beispielsweise
Daten von einem File und verarbeite sie.
Es muá somit (wenn es strukturiert sein
m”chte) vor dem Lesen jedes einzelnen
Zeichens das Betriebssystem befragen, ob
das File vielleicht schon ersch”pft ist.
Das ergibt beispielsweise in Pascal
endlose Konstrukte des Strickmusters:

   WHILE not eof(input) DO
   WHILE not eoLn(input) DO
   BEGIN
      READ (input,char);
      IF char=...THEN
         ....
         IF or(eof(input),eoLn(input)
         THEN schweinkram;
         ELSE  read (input,nochn_char);
               ....
         ENDIF;
         ....
      ENDIF;
   END;

Viel einfacher haben es da Sprachen, die
keinerlei Anspruch auf strukturiertes
Programmieren erheben. Das obrige
Kuddelmuddel lieáe sich in Fortran etwa
so umgehen:

      READ (input,char,err=100)
      READ (input,nochnchar,err=200)
      ...
 100  ...
 200  ...

Hier wird (v”llig unstrukturiert) der
Programmfluá im Fehlerfall unterbrochen
und an den durch 100 und 200
gekennzeichneten Stellen fortgesetzt.
Ein „hnliches GOTO-Konstrukt bietet auch
Pascal an. Jedes gute Lehrbuch bittet
aber darum es m”glichst nie zu benutzen.
Als einzigen tolerierbaren Zweck wird
meist die Fehlerbehandlung angegeben.
Ein sehr treffender Beleg dafr, daá
selbst von V„tern der strukturierten
Programmierung die Fehlerbehandlung
Kopfzerbrechen bereitet.

Einen g„nzlich anderen Anwendungsfall
fr Fehlerbehandlung stellt die Ausgabe
von Informationen im Fehlerfall dar. So
wird h„ufig die komplette Aufrufliste
im Fehlerzustand ausgegeben. Dies k”nnte
etwa so aussehen:

FEHLER divide by Zero AUFGETRETEN.
   Der Fehler geschah in Wort: 0/
               aufgerufen von: MEINWORT
               aufgerufen von: TEST
               aufgerufen von: EDIT
               aufgerufen von: L

Derartige POST-MORTEM-DUMPS erm”glichen
i.a. ein schnelles Lokalisieren des
Fehlers. Sie enthalten des ”fteren nicht
nur die Aufrufhierarchie sondern
diverse Register- und Variablen-Inhalte
zum Zeitpunkt des Fehlers (am besten
noch aus allen Unterprogrammen...),
sodaá sie manchmal den Benutzer eher in
hunderten von Seiten Papier ersticken,
als ihm bei der Fehlersuche zu helfen.
Aber selbst dagegen sind Kr„uter
gewachsen. Logitech's Modula-2-Compiler
teilt dem Benutzer auáer einer sehr
knappen Fehlerbeschreibung nichts mit
und schreibt ersatzweise den kompletten
Systemzustand auf Diskette, wo man ihn
anschlieáend mit einem
Post-Mortem-Debugg-Programm umgraben
kann. Es frage mich bitte niemand, was
passiert, wenn die Diskette voll war.
Ruft der Fehler dann einen erneuten
Post-Mortem-Dump hervor?

Die sch”nste, allgemeinste Art der
Fehlerbehandlung ist das
CATCH-THROW-Konstrukt aus TLC-Lisp.
