User Tools

Site Tools


k11:k11.5:k11.5.0.1:start

11.5.0.1 Error handling 2

Error management in the Gambas programming language also includes the topics of recognising errors, catching errors and handling errors. For this purpose, Gambas provides the instructions TRY, FINALLY, CATCH, ERROR, DEBUG as well as the error class Error, a global, read-only Boolean variable Error and error numbers as well as error descriptions, which are described in this chapter.

11.5.0.1.1 Error Class Error (gb)

The Error class has these static, read-only properties:

PropertyData typeDescription
Backtrace String[]Returns a backtrace of the stack state of the function call when the last error occurred. The first entry of the string array is the lowest function call. If no debugging information was available or if no error occurred, this property returns NULL.
ClassClassReturns the name of the class in which the last error occurred.
CodeIntegerReturns the last error number.
TextStringReturns the last error message - corresponding to the associated error code in English.
WhereStringReturns a string describing the position of the last error in the source code.

Table 11.5.0.1.1 : Properties of the Error Class

Instead of the Error.Backtrace property of the Error class, you can also use the static property System.Backtrace (gb) with Static Property Read Backtrace As String[ ]. In both cases, a string array is returned to you that you can read out and display.

The Error class Error has only three methods:

MethodDescription
Clear()Sets the error code to 0 and the error message to NULL. You can use this method if you handle the error within a procedure and then set the properties Error.Code to 0 and Error.Text to NULL.
Propagate()The method ensures that the error is triggered again.
Raise( argMessage As String )Raises an error defined by the user. The error message in argMessage can be freely defined in the source code.

Table 11.5.0.1.2 : Methods of the error class

11.5.0.1.2 Statement DEBUG

DEBUG Expression [ { ; | ;; | , } Expression ... ] [ { ; | ;; | , }  ]
  • The instruction prints a list of expressions on the standard error output. But only if the programme was compiled with debugging information. You can change the setting in the “Create executable” dialogue. The default setting is “Keep debugging information in the executable file”.
  • The position of the DEBUG statement in the source code is prepended to everything.
  • The expressions are converted into strings with the Str$ function, which takes into account the current location parameters such as GUI language, number, currency, date and time formats, character set and keyboard layout (locale)!
  • If there is no semicolon and no comma after the last expression, a newline character is output after the last expression.
  • If the semicolon is doubled, a space is output between each expression.
  • If a comma is used instead of a semicolon, a tab character (ASCII code 9, gb.Tab) is output to separate each expression.
  • The list of expressions is preceded by the name of the class, a full stop, the name of the procedure, a colon and the line number such as:
FMain.GetStart.69: /tmp/gambas.1000/13839/New.tmp/new.md.

The following example was about checking various paths. The instruction DEBUG - switched on by the boolean variable bDebug - was preferred to an instruction PRINT, because the line numbers in the source code were also of interest:

  Public bDebug As Boolean
 
  bDebug = True
 
  sBasicConfigDir = Desktop.ConfigDir &/ sVendor &/ Lower(sAppName)
 
  If bDebug Then Debug sBasicConfigDir   
 
  If Not Exist(sBasicConfigDir) Then Shell.MkDir(sBasicConfigDir)
  hSettings = New Settings(sBasicConfigDir &/ File.SetExt(Lower(sAppName), "conf")) 
 
  If bDebug Then Debug sBasicConfigDir &/ File.SetExt(Lower(sAppName), "conf")
  ...
  sCurrentMDFilePath = sTempDir &/ "new.md"
 
  If bDebug Then Debug sCurrentMDFilePath

Outputs in the console of the IDE:

FMain._new.49: /home/hans/.config/gambasbook/mdeditor
FMain._new.52: /home/hans/.config/gambasbook/mdeditor/mdeditor.conf
...
FMain.GetStart.69: /tmp/gambas.1000/13839/New.tmp/new.md

===== 11.5.0.1.3 Statement ERROR =====<code_b_3>

The statement prints a list of expressions on the standard error output - just like the PRINT statement. If you were writing a command-line program, this statement would be the non-graphical equivalent of Message.Error().

If in the IDE, in the Debug menu, you activate the entries 'Use Terminal Emulator' and “Redirect Standard Error Output” both with ✔, then DEBUG and ERROR output will be displayed in the IDE console and PRINT output in the terminal. However, if 'Use terminal emulator' is active and redirection is disabled, then DEBUG, ERROR and PRINT output will be displayed in the terminal:

Figure 11.5.0.1.1: DEBUG, ERROR and PRINT outputs in the (IDE) terminal.

The standard output can be redirected by the ERROR TO statement ( ▷ chapter 6.2.0.14 ERROR TO DEFAULT). A redirection is simply implemented:

DIM aFile As File

  aFile = OPEN User.Home &/ "error_ping.log" FOR CREATE ' or APPEND

  OUTPUT TO aFile  
  ...
    Error ...
  ...
  CLOSE aFile

This source code snippet redirects the output of the error statement to the specified file.

11.5.0.1.4 Global Variable Error

The boolean variable Error - global and read-only - returns the value True if an error has occurred. Use it directly after a Try statement to know whether the statement specified there failed or not. To get more information about the error, use the (error) class Error (gb) with success.

Example: Deleting a file

Public Sub btnKillFile_Click()
 
  Dim sMessage, sFilePath As String
 
  sFilePath = User.Home &/ "Temp" &/ "tmp.text"
 
  Try Kill sFilePath
  If Error Then Print "Error! The file `" & File.Name(sFilePath) & "` cannot be deleted!"
  If Error Then Error Subst("&1 '&2' &3", ("Error! The file"), File.Name(sFilePath), ("cannot be deleted!"))
  If Error Then Print Error.Class.Name;; Error.Code;; Error.Text;; Error.Where
  If Error Then Error "Error³!";; Error.Text
  If Error Then Error Error
  If Error Then Debug Error.Text
'--------------------------------------------------------------------------------------------------------
  If Error Then 
     sMessage = "<b><font size='+1', color='DarkRed'>"
     sMessage &= ("Error")
     sMessage &= "</b></font><hr>"
     sMessage &= "The file '" & File.Name(sFilePath) & "' cannot be deleted.<br>"
     sMessage &= Error.Text & "!<br>"
     sMessage &= ("The error was raised in the source code line") & " " & Split(Error.Where, ".")[2] & "."
     Message.Error(sMessage)
  Endif
'--------------------------------------------------------------------------------------------------------
  Error Error
End

The following is the output in the console of the IDE:

Error! The file `tmp.text` cannot be deleted!
Error! The file 'tmp.text' cannot be deleted!
FMain 45 File or directory does not exist FMain.btnKillFile_Click.10
Error³! File or directory does not exist
True
FMain.btnKillFile_Click.16: File or directory does not exist
True

BILD 2

Figure 11.5.0.1.2: Error message

Comment

  • The `Try Kill sFilePath` instruction triggers an error if, for example, the file to be deleted does not exist or the permission to delete the file is missing.
  • In the example, the file path points to a file that does not exist, so an error is guaranteed to be raised. In this syntax in the above source code (one could say in the “evaluation context”), `Error` behaves like a global read-only variable managed by the interpreter.
  • Assignments like `Error = …` are not possible, however, and result in a syntax error.
  • This evaluation context includes constructs like `Variable = Error`, `Print Error` or `If Error then …`.
  • Opposite the evaluation context is the statement context. If `Error` is syntactically in a place where a statement is expected, then it behaves like a statement. The following line is for demonstration purposes only:
If Error Then Error Error
  • The first Error is in the “evaluation context”. Error stands for the above boolean variable.
  • The second Error after `Then` is a statement - as it is in the statement context.
  • The third Error stands for the value of the boolean variable Error.
  • Short version: If the variable Error has the value True, then the instruction Error outputs the value Variable Error - i.e. True as expected.
  • 11.5.0.1.5 Example for the use of the method Error.Raise(…)
  • The value of a base for a number value system is to be read in via the property Textbox.Text, which is to be used in the programme. The following applies to the base: base ∈ ℤ (data type integer), base ≥ 2 and base ≤ 32. Here you can see the complete source code for the dialogue:
' Gambas class file
 
Property Read Basis As Integer
Private $iBasis As Integer
 
Private Function Basis_Read() As Integer
  If FSetBasisDialog.ShowModal() = 1 Then 
     Return $iBasis
  Else
     Return 0
  Endif
End
 
Public Sub Form_Open()
  FSetBasisDialog.Resizable = False
End
 
Public Sub txbBasis_Activate()
  SetBasis()  
End
 
Public Sub btnOK_Click()
  SetBasis()
End
 
Private Function CheckInput(argInput As String) As Integer
 
  Dim iValue As Integer
 
  If Not argInput Then Error.Raise(("Die Eingabebox ist leer!"))
  If Not IsInteger(argInput) Then 
     Error.Raise(("Der Text kann <b>nicht</b> in eine Integer-Zahl konvertiert werden!"))
  EndIf
 
  iValue = Val(argInput)
 
  If iValue < 2 Then Error.Raise(("Die Basis ist kleiner als 2!"))
  If iValue > 32 Then Error.Raise(("Die Basis ist größer als 32!"))
 
  Return iValue
 
End
 
Private Sub SetBasis()
 
  $iBasis = CheckInput(txbBasis.Text)
  FSetBasisDialog.Close(1)  
 
  Catch  
    Message.Error(Error.Text)
    Error.Clear()
    txbBasis.Clear()
    txbBasis.SetFocus()
 
End

Comment

  • The validation of the input takes place in the function CheckInput(argument).
  • Errors that occur are raised by the programmer with suitably defined error message using the Error.Raise(error_description) method.
  • If an error occurs with the assignment $iBasis = CheckInput(txbBasis.Text), the error is safely caught with CATCH and the corresponding user-defined error message is issued, otherwise the CATCH block is skipped.

11.5.0.1.6 Example of the use of the Error.Clear() and Error.Propagate() methods

Preliminary note: In the source code of Gambas 3.12.2 you will not find a line with the method Error.Clear() and only 3 times the method Error.Propagate() is used. That says a lot about the importance of these two methods!

When an error is raised, the Gambas interpreter stops the execution of the current frame and looks for error handlers such as try or catch. If it cannot find them, the interpreter goes up the call stack and looks for error handlers there one by one until the global level is reached. There, as a last resort, the interpreter looks for the method `Static Public Sub Application_Error()` in the Start class. If the error could not be corrected, the interpreter issues an error message and terminates the programme.

To observe the automatic unwinding of the stack, look at the following module source code and the resulting output:

' Gambas module file
 
Public Sub Main()
    f()
  End
 
  Public Sub f()
    Try g()
    If Error Then 
       Print "\nError-Backtrace:\n----------------"
       Print Error.Backtrace.Join("\n")
    Endif
  End
 
  Public Sub g()
    h(4)
    Print "Error from h(arg) will jump over this. Jumps to FINALLY"
 
    Finally
      Print "\nPassing through g()"
    ' Error.Clear()
      Error.Propagate() ' Apparently handles the error by triggering it again.
  End
 
  Public Sub h(x As Integer)    
    Print "x = "; CStr(x); " | f(x) = "; 1 / x
    h(x - 1) ' Recursion - but without termination condition
    Print "Execution of h stops for x = 0 before we're here!"
  End

Outputs in the IDE console:

x = 4 | f(x) = 0,25
x = 3 | f(x) = 0,33333333333333
x = 2 | f(x) = 0,5
x = 1 | f(x) = 1

Passing through g()

Error-Backtrace:
----------------
Main.h.27
Main.h.28
Main.h.28
Main.h.28
Main.h.28
Main.g.16
Main.f.8
Main.Main.4

You could say that the Try and Catch statements take the interpreter out of the exceptional state. Unwinding of the batch is stopped and normal execution resumes. But if you have several “If Error Then” constructs in the source code, then you must use the Error.Clear() method after handling an error to avoid handling it again! For comparison, comment out the line calling the Error.Clear() method and then look at the output again!

11.5.0.1.7 Error numbers and error messages

Within an error handler, you can also target the displayed error numbers, which you can read via the Error.Code property of the Error (gb) class. For a complete list, see http://gambaswiki.org/wiki/error. Use the error numbers to generate meaningful error messages in German, because behind each error number is a short description of the triggered error in English, as the following examples show as an example:

(43)  Access forbidden
(44)  File name is too long
(45)  File or directory does not exist
(46)  File is a directory
(47)  Read error
(48)  Write error
Cannot find dynamic library (60)
Cannot find symbol in dynamic library (61)
Cannot load class (2)
Cannot load component (27)
Cannot open file (35)

The following source code excerpt sets an error message in German in the Select…Case control structure in the Catch block for selected error numbers. The error number is read from the Error.Code property:

Public Sub btnSaveFile_Click() 
 ' -> Saves the content of TextArea1 in the file to which the path in TextBox1 leads.
   Dim hFile As Stream
   Dim iCount As Integer
   Dim sErrorText As String
 
   hFile = Open TextBox1.Text For Write
   ...
     Write #hFile, bWrite, 1    
   ...  
 ' -> Close the stream in any case
   Finaly
     Close #hFile
   Catch
   Select Case Error.Code
     Case 43
       sErrorText = ("You do not have the rights to save this file.")
     Case 44
       sErrorText = ("The file name is too long.")
     Case 45
       sErrorText = ("The file or folder does not exist.")
     Case 46
       sErrorText = ("The path leads to a folder.")
     Case 48
       sErrorText = ("Error when writing to the file.")
     Case Else
       sErrorText = ""
   End Select  
 ' -> Output information about the triggered error
   Message.Error("Error-Code: " & Error.Code & "\n" & "bei " & Error.Where & "\n" & sErrorText)
 
End

Download

The website uses a temporary session cookie. This technically necessary cookie is deleted when the browser is closed. You can find information on cookies in our privacy policy.
k11/k11.5/k11.5.0.1/start.txt · Last modified: 23.09.2023 by honsek

Page Tools