ON ERROR: Difference between revisions

From QB64 Phoenix Edition Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 27: Line 27:
** Organize your code so that '''_NEWHANDLER''' is not executed 1000s of times in a tight loop, best use is at the entry point of a [[SUB]] or [[FUNCTION]]. Place '''_LASTHANDLER''' at the end point, but make sure it's also called when using [[EXIT SUB]] or [[EXIT FUNCTION]].
** Organize your code so that '''_NEWHANDLER''' is not executed 1000s of times in a tight loop, best use is at the entry point of a [[SUB]] or [[FUNCTION]]. Place '''_LASTHANDLER''' at the end point, but make sure it's also called when using [[EXIT SUB]] or [[EXIT FUNCTION]].
** Memory crashes {{Text|may only happen on unbalanced use|red}} of '''_NEW-/_LASTHANDLER''', if you have much more (several 10000s) '''_NEWHANDLER''' than '''_LASTHANDLER''' executions, so if you take the care and follow given recommendations, then everything will just work fine.
** Memory crashes {{Text|may only happen on unbalanced use|red}} of '''_NEW-/_LASTHANDLER''', if you have much more (several 10000s) '''_NEWHANDLER''' than '''_LASTHANDLER''' executions, so if you take the care and follow given recommendations, then everything will just work fine.
** The use of '''_LASTHANDLER''' is always save. If the history chain has more enries, then it is synonymous to the ''0 (zero)'' parameter of the legacy syntax.
** The use of '''_LASTHANDLER''' is always save. If the history chain has no more enries, then it is synonymous to the ''0 (zero)'' parameter of the legacy syntax, i.e. disabling program based error trapping.
** The use of the legacy {{InlineCode}}{{Cl|ON ERROR}} {{Cl|GOTO}} {{Text|0|#F580B1}}{{InlineCodeEnd}} will also completly reset/clear the handler history chain.
** The use of the legacy {{InlineCode}}{{Cl|ON ERROR}} {{Cl|GOTO}} {{Text|0|#F580B1}}{{InlineCodeEnd}} will also completly reset/clear the handler history chain.



Revision as of 00:36, 24 August 2024

The ON ERROR statement is used in conjunction with GOTO to handle errors in a program.


Syntax

Legacy QuickBASIC/QBasic
ON ERROR GOTO {lineNumberOrLabel | 0}
QB64-PE extension
ON ERROR GOTO {_LASTHANDLER | _NEWHANDLER lineNumberOrLabel}


Parameters

  • lineNumberOrLabel must be a line number or program label in the main part of your program usually placed after the END or SYSTEM statement. Line numbers or labels inside of SUB or FUNCTION blocks are not allowed.
  • 0 (zero) will disable all program based error handling, i.e. errors remain unhandled.


Description

  • An unhandled error in a program will cause execution to stop and an error message box is displayed to the user, who can choose to continue (ignore the error - which could have unexpected results) or end the program.
  • Use ON ERROR when your program performs operations that are likely to generate errors, like file access operations.
  • ON ERROR statements can be in the main code section or in SUB or FUNCTION procedures, but the line number or label must always be in the main code section.
  • ON ERROR statements take precedence in the order they are encountered, i.e. the most recently set handler is used. Subsequent ON ERROR statements will override the previous one.
  • ON ERROR GOTO 0 can be used to disable program based error trapping and give default error message boxes.
  • GOTO is required in the statement. Cannot use GOSUB.
  • QB64 and QB64-PE do not support the PDS (QuickBASIC 7) ON ERROR RESUME NEXT statement.

  • Since QB64-PE v3.15.0 the _NEWHANDLER and _LASTHANDLER keywords can be used to build up a history chain of the used error handlers. This is especially useful inside SUB or FUNCTION code provided in external libraries, when the handlers are unknown (see Example 3).
    • Works also over several nested or recursive sub-/function calls, but care must be taken for correct exit conditions to avoid crashes due to extensive memory usage. Each use of _NEWHANDLER should have a matching use of _LASTHANDLER.
    • Organize your code so that _NEWHANDLER is not executed 1000s of times in a tight loop, best use is at the entry point of a SUB or FUNCTION. Place _LASTHANDLER at the end point, but make sure it's also called when using EXIT SUB or EXIT FUNCTION.
    • Memory crashes may only happen on unbalanced use of _NEW-/_LASTHANDLER, if you have much more (several 10000s) _NEWHANDLER than _LASTHANDLER executions, so if you take the care and follow given recommendations, then everything will just work fine.
    • The use of _LASTHANDLER is always save. If the history chain has no more enries, then it is synonymous to the 0 (zero) parameter of the legacy syntax, i.e. disabling program based error trapping.
    • The use of the legacy ON ERROR GOTO 0 will also completly reset/clear the handler history chain.


Availability

  • The _NEWHANDLER and _LASTHANDLER functionality is introduced in QB64-PE v3.15.0.


Examples

Example 1
Using an error handler that prints the error and then continues with the next program line.
'install our own error handler
ON ERROR GOTO errHandler
'now simulate an "Out of Memory" error
ERROR 7
'our error handler will return to this point
PRINT "Error was handled.": PRINT
'now we disable our error handler
ON ERROR GOTO 0
COLOR 9: PRINT "Handler disabled.": COLOR 7
'without our own error handler the following error is reported
'in the usual message box popup again
PRINT "The next error will no longer be handled, press any key ...": SLEEP
ERROR 7
END

'the error handler label must be part of the main program, local
'labels inside a SUB/FUNCTION are not allowed for error handlers
errHandler:
COLOR 10: PRINT "Start handling error"; ERR; "on program file line"; _ERRORLINE;
BEEP: PRINT "... done.": COLOR 7
RESUME NEXT 'returns execution to the code following the error
Start handling error 7 on program file line 6 ... done.
Error was handled.

Handler disabled.
The next error will no longer be handled, press any key ...

Example 2
Using an alternative error handler in a SUB procedure.
ON ERROR GOTO mainHandler
ERROR 7
PRINT "Error was handled.": PRINT
LegacyErrorTest
PRINT "Error was handled.": PRINT
ERROR 7
PRINT "Error was handled.": PRINT
ON ERROR GOTO 0
COLOR 9: PRINT "Handler disabled.": COLOR 7
PRINT "The next error will no longer be handled, press any key ...": SLEEP
ERROR 7
END

'the error handler label must be part of the main program, local
'labels inside a SUB/FUNCTION are not allowed for error handlers
mainHandler:
COLOR 10: PRINT "Main handler starts handling error"; ERR; "on program file line"; _ERRORLINE;
BEEP: PRINT "... done.": COLOR 7
RESUME NEXT
'an alternative error handler which we set from within a SUB/FUNCTION
'however, the error handler label must still be part of the main program
subHandler:
COLOR 12: PRINT "Sub handler starts handling error"; ERR; "on program file line"; _ERRORLINE;
BEEP: PRINT "... done.": COLOR 7
RESUME NEXT

SUB LegacyErrorTest
'the next line overrides the currently active "mainHandler"
'with our new "subHandler"
ON ERROR GOTO subHandler
ERROR 7
'unfortunately the legacy QuickBASIC/QBasic syntax has no function to
'restore back to the old handler, so you need to know which handler was
'active and restore that manually
ON ERROR GOTO mainHandler
END SUB
Main handler starts handling error 7 on program file line 4 ... done.
Error was handled.

Sub handler starts handling error 7 on program file line 33 ... done.
Error was handled.

Main handler starts handling error 7 on program file line 8 ... done.
Error was handled.

Handler disabled.
The next error will no longer be handled, press any key ...

Example 3
Same as example 2, but using QB64-PE specific extensions _NEWHANDLER and _LASTHANDLER.
ON ERROR GOTO mainHandler
ERROR 7
PRINT "Error was handled.": PRINT
QB64peErrorTest
PRINT "Error was handled.": PRINT
ERROR 7
PRINT "Error was handled.": PRINT
ON ERROR GOTO 0
COLOR 9: PRINT "Handler disabled.": COLOR 7
PRINT "The next error will no longer be handled, press any key ...": SLEEP
ERROR 7
END

mainHandler:
COLOR 10: PRINT "Main handler starts handling error"; ERR; "on program file line"; _ERRORLINE;
BEEP: PRINT "... done.": COLOR 7
RESUME NEXT
subHandler:
COLOR 12: PRINT "Sub handler starts handling error"; ERR; "on program file line"; _ERRORLINE;
BEEP: PRINT "... done.": COLOR 7
RESUME NEXT

SUB QB64peErrorTest
'the next line overrides the currently active "mainHandler"
'with our new "subHandler", but the _NEWHANDLER keyword explicitly
'designates this as override and to remember the former handler
ON ERROR GOTO _NEWHANDLER subHandler
ERROR 7
'now the following _LASTHANDLER syntax can easily restore back
'to the former handler without we need to know which one it was,
ON ERROR GOTO _LASTHANDLER
END SUB
Main handler starts handling error 7 on program file line 4 ... done.
Error was handled.

Sub handler starts handling error 7 on program file line 30 ... done.
Error was handled.

Main handler starts handling error 7 on program file line 8 ... done.
Error was handled.

Handler disabled.
The next error will no longer be handled, press any key ...
Examples by RhoSigma


See also



Navigation:
Main Page with Articles and Tutorials
Keyword Reference - Alphabetical
Keyword Reference - By usage
Report a broken link