The following article was printed in June 1986 of the magazine „MC".
|
Hans-Jürgen Schmidt |
ON-ERROR
"-Anweisungen vieler Basic-Interpreter zurück.
Nach eingehender Analyse der CP/M-Turbo-Pascal-Fehlerbehandlung wurde ein Weg gefunden, durch einen eigenen Error-Handler Runtime-Fehler abzufangen1.
IORESULT
und den entsprechenden Compiler-Directiven wird dem Benutzer eine eigene Behandlung von I/O-Errors ermöglicht.
Bei Runtime-Errors ist eine Fehlerbehandlung durch den Benutzer nicht vorgesehen.
RUNERROR
angesprungen.
| ||
[Hier der abweichende Error-Handler von Turbo-Pascal 3.0] |
SET_ERROR_HANDLER
(Zeile 76) wird bei der Adresse RUNERROR
ein „JUMP ERROR_HANDLER
" eingetragen, nachdem der Original-Code in RUN_TIME_ERROR_BAK
gerettet wurde (SWITCH = ON = true
).
Durch Restaurieren mit dem Original-Code kann der ERROR_HANDLER
wieder abgeschaltet werden (SWITCH = OFF = false
).
|
Bei TURBO Pascal 3.0 muss die Zeile 85 geändert werden in:
85 RUN_TIME_ERROR : JUMP_VECTOR absolute $2029; |
ERROR-HANDLER
(Zeile 49) wurde als Real
-Funktion deklariert, da es hier im wesentlichen auf Fehler bei Real
-Arithmetik ankommt.
Die Fehlernummer, die im Akku übergeben wird, muß ganz am Anfang der Routine mit einem Inline
-Statement in eine Variable (ERROR_CODE
) gerettet werden.
In einer Fallunterscheidung (CASE ERROR_CODE
) können die einzelnen Fehlertypen unterschiedlich behandelt werden.
Hier sind fast nur Leer-Statements eingetragen.
Nach Bedarf können z.B. Klartext-Fehlermeldungen ausgegeben werden.
Bei den Fehlern $01
und $02
kann man auch mit der Zuweisung „ERROR_HANDLER := 1E38
" mit „fast unendlich" weiterrechnen lassen.
Eine weitere Möglichkeit ist das Führen einer Statistik, wann und wie oft welche Fehler aufgetreten sind.
HALT
verlassen oder mit WARM_START
nochmals von vorne ablaufen lassen, wie z.B. bei einer Heap-Stack-Kollision (Zeile 63).
IORESULT
bei I/O-Fehlern dient die Funktion ERROR_NUM
bei Runtime-Fehlern.
Sie liefert den zuletzt aufgetretenen ERROR_CODE
(0 = kein Fehler) und setzt ihn zurück.
Man muß also bei einem komplexen arithmetischen Ausdruck nicht vor jeder einzelnen Operation eine potentielle Fehlerbedienung abprüfen
(Divisor = 0 ?, ln
mit negativem Argument ?, führt Argument von exp
zu Overflow ? usw.).
Es genügt, nach der Abarbeitung des komplexen Ausdrucks einmal ERROR_NUM
auf 0 zu testen.
WARM_START
bisher ermittelte Daten erhalten bleiben können.
Zu diesem Zweck wird die Variable FIRST_TIME
als „typed constant
" mit dem Wert „true
" deklariert (Zeile 20).
Nach dem Laden des Programms wird im if
-Statement in Zeile 150 der then
-Block ausgeführt.
In diesem Block wird FIRST_TIME
auf „false
" gesetzt, die Initialisierung der Datenstrukturen vorgenommen und der ERROR_HANDLER
aktiviert.
Bei einem Runtime-Fehler, für den im ERROR_HANDLER
die Prozedur WARM_START
aufgerufen wird, beginnt das Programm von vorne.
Da nun FIRST_TIME
„false
" ist, wird im if
-Statement der else
-Block ausgeführt.
Da die Datenstrukturen nicht wieder initialisiert werden, bleibt ihr Wert.
Durch einen Dummy-Aufruf von ERROR_NUM
wird ERROR_CODE
gelöscht.
|
1. | Bei anderen Compilern lassen sich Fehler-Routinen einfacher implementieren, hier am Beispiel des Pascal MT+ Compilers von Digital Research und des Pro Pascal Compilers von Prospero Software (Auszug aus den Handbüchern): |
Pascal MT+ Compiler |
---|
4.6.3 User-supplied Handlers You can write your own @ERR routine instead of using the system routine. Declare the routine as follows: PROCEDURE @ERR(ERROR:BOOLEAN; ERRNUM:INTEGER); Your version of @ERR should check the ERROR variable and exit if it is FALSE. If the value is TRUE, you can decide what action to take. To use @ERR instead of the routine in PASLIB, link your routine ahead of PASLIB to resolve the references to @ERR. The values of ERRNUM are in Table 4-2. |
Pro Pascal Compiler |
9.3.5 ownerr This procedure is provided to enable the user to perform bis own exception handling, as an alternative to the normal reporting of run-time errors. The procedure ownerr installs a procedure nominated by the user as his error handler, which will then receive control in the event of any error arising. The handler is invoked for all types of error, but has the option of processing some and leaving the others to be reported at the console in the usual way. The handler must be written to the parameter specification shown below in the declaration of ownerr. PROCEDURE ownerr (PROCEDURE handler (errorletter: char; erroraddress: integer; VAR errorstring: string; fatal: boolean; VAR processed: boolean) ); EXTERNAL; The procedure nominated as the error handler when ownerr is called must be at the outer level. (It can itself be an EXTERNAL, for example in a library.) Its parameters must agree with the list above, where the purpose of the first four is to provide "handler" with the information from the standard error message - letter, address, supplementary string (which may be empty), and fatal/recoverable flag. The fifth ("processed") is an inout parameter defaulted to false. If handler leaves this as it is, then on exit the normal report will be produced; if it is set to true, reporting will be skipped. |
Scanned by
Werner Cirsovius
Februar 2005
© Franzis' Verlag