PROPER ERROR MANAGEMENT IN FREEBASIC

Written by Stéphane Richard (Mystikshadows)

INTRODUCTION:

Don't be scared by the title. Believe it or not, it's amazing the problems that can be solved just by taking the time to implement a proper error management system into your code. Error management is often overlooked today no matter what platform your projects are intended. Why you ask? Simply because it is seen as a big beast to implement. This is usually because many coders who claim this tend to implement error management after the game or application is developed already. Indeed, to have a good control over the error management system, it needs to be implemented before and during the coding of the application, not after. Then, you'll see, error management won't be the big beast it is claimed to be.

This article will attempt to cover error management as it could be implemented in FreeBasic as well as see how to manage the errors themselves. Indeed, the application doesn't need to be halted everytime an error occurs, we'll see why here and what you can do instead of halting the program.

WHAT EXACTLY IS ERROR MANAGEMENT:

The best way to explain this concept is to start by defining what an error is in this context. In this document we'll be covering the runtime errors not the syntax errors because the compiler reports those errors so you can correct them. Runtime errors are, well, errors that happen while your program is executing itself. Error management is the art of controling these runtime errors, reporting the problem and taking the proper action for these errors. The first thing I need say is that I split errors up into three general categories. There are the software errors, operating system errors and the hardware errors. Let me explain these:

The reason why I split the errors that can occur into these three categories is mainly to split the error management task into 3 simpler functions. It is also because I treat these three groups of error differently. Like I mentionned, not all errors need the same kind of management nor do they need the same type of exit procedure. The art of deciding which method to use and when to return to the program itself and when to halt everything and go back to the operating system is what proper error management is all about.

WHAT TO DO WHEN AN ERROR IS ENCOUNTERED:

Again I can only share what I know and what I use. So in a typical error management scenario, what you'll see here is how I would cope with the situations. When you get an error, in freebasic and alot of other BASICs i'm familiar with, the error number of the problem can be found in the Err variable. First thing I do is look up the error in a table like this one to know what exactly the error actually is. Then according to the error number, I have the application report the error (if needed) and perform certain recovery functions (if needed) and finally the application can continue (once all the precautions are taken). Here's a rundown of these situations, and what could be done with them. Atleast, it's what I'd do when I encounter them. This is a list of circumstances that could potentially cause errors and what one could do with them. These are suggestions (as in what would/could be considered proper thing to do) in some cases, you might need to halt on every error (really depends on the nature of the application).

Typically, these are the errors you need to be careful and pay special attention to. There are other types of errors but usually they can be handled without being reported. How you treat these errors will vary based on the importance of the situation or the part of the application that is causing the error. If you're saving you'll want to give a few options to see if there could be a way to not loose the file for example. As files are usually quite important and typically not created just for fun. Now that we know the types of errors and the situations and circumstances that can cause them, we'll now look at what good error management could be at the level of the language itself, in our case, FreeBasic.

HOW TO CODE FOR THE ERRORS IN FREEBASIC:

The first thing to know about coding for error trapping and management is what the language offers as tools for error control. In the case of FreeBasic, errors are trapped as events so to speak and a series of statements are provided to manage them. Let's start by looking at an empty skeletal code sample to start to situate where things go. In FreeBasic errors are best managed at the sub or function level. So hor first example will be a function example.

FUNCTION OpenDatabaseFile(FilePath AS STRING) AS INTEGER ' ----------------------------------- ' First we Turn On Error Management ' ----------------------------------- ON ERROR GOTO ErrorManager ' -------------------------------------------------------- ' Here we put the code that the function should perform ' -------------------------------------------------------- OpenDatabaseFile = 0 ' ----------------------------------------------------- ' When we're exiting we can turn off Error management ' ----------------------------------------------------- ON ERROR GOTO 0 ' ----------------------------------------------- ' We now need to exit the function so the error ' manager part isn't executed accidentally ' ----------------------------------------------- EXIT FUNCTION ErrorManager: ' --------------------------------- ' Error Management Code goes here ' --------------------------------- RESUME NEXT END FUNCTION

Now let's see what we have here. The first line in the function turns Error trapping on so to speak by telling the program that if an error occurs, go to the ErrorManager label to execute the code that's there. After that first line goes the code to what the function should be doing. Here I just assign 0 as the return value of the function. But the actual opening of the database would have been right before that assignment. Next we turn error management off with the ON ERROR GOTO 0 <- (zero). This is how you turn off error management in FreeBasic (and most basic dialects today). Since in FreeBasic error trapping is at the sub or function level you can omit this line as it will be turned off at the end of the subroutine. We then exit the function with EXIT FUNCTION. I can stress the importance of that EXIT FUNCTION statement. If it is not present the code will naturally continue all the way to the label ErrorManager and execute that code too because it's part of the function. So you need to exit the function before the program gets a chances to get to that error manager. If an error Occurs, the program will jump to that label and execute the code, that's the only time you'll want to execute that code. Finally the error management could should Resume execution of the program with RESUME NEXT if the error is critical enough to warrant exiting the program it should be done before the RESUME NEXT statement. We'll see examples of this later in this document.

Now let's put some code in here to see what we can do. Taking our sample function which would typically open a database file it's important to note that error management in FreeBasic or any other languages should be context sensitive. For example, if this function opens a database file, it wouldn't make sense to manage calculation errors like division by zero because you won't be calculating in this function. That's what I mean by you have to keep things in context. Here's some code.

FUNCTION OpenDatabaseFile(FilePath AS STRING) AS INTEGER ' ----------------------------------- ' First we Turn On Error Management ' ----------------------------------- ON ERROR GOTO ErrorManager ' -------------------------------------------------------- ' Here we put the code that the function should perform ' -------------------------------------------------------- OpenDatabaseFile = 0 ' ----------------------------------------------------- ' When we're exiting we can turn off Error management ' ----------------------------------------------------- ON ERROR GOTO 0 ' ----------------------------------------------- ' We now need to exit the function so the error ' manager part isn't executed accidentally ' ----------------------------------------------- EXIT FUNCTION ErrorManager: ' --------------------------------- ' Error Management Code goes here ' --------------------------------- SELECT CASE ERR CASE 2 ' The system cannot find the file specified. Message$ = "The system cannot find the file specified." CASE 3 ' The system cannot find the path specified. Message$ = "The system cannot find the path specified." CASE 4 ' The system cannot open the file. Message$ = "The system cannot open the file." END SELECT PRINT Message$ OpenDatabaseFile = Err END FUNCTION

As you can see, I only manage file related errors and that is the way it should be as well. This is a basic error manager in that it only displays the error that just occured and exit the subroutine, not the whole program, just the faulty function. The code that called this function would either continue with the code or stop should the error justify it. You can use error management to provide alot more information that this however (which is useful, for instance, in a testing and debugging session) where the aim of the error management isn't only to trap errors but to fix them whenever possible). Here's the same code with a bit more useful detail if you wanted to search for the bug.

FUNCTION OpenDatabaseFile(FilePath AS STRING) AS INTEGER ' ----------------------------------- ' First we Turn On Error Management ' ----------------------------------- ON ERROR GOTO ErrorManager ' -------------------------------------------------------- ' Here we put the code that the function should perform ' -------------------------------------------------------- OpenDatabaseFile = 0 ' ----------------------------------------------------- ' When we're exiting we can turn off Error management ' ----------------------------------------------------- ON ERROR GOTO 0 ' ----------------------------------------------- ' We now need to exit the function so the error ' manager part isn't executed accidentally ' ----------------------------------------------- EXIT FUNCTION ErrorManager: ' --------------------------------- ' Error Management Code goes here ' --------------------------------- SELECT CASE ERR CASE 2 ' The system cannot find the file specified. Message$ = "The system cannot find the file specified." & _ "In the OpenDatabaseFile Function with " & _ FilePath & " Passed as a parameter." CASE 3 ' The system cannot find the path specified. Message$ = "The system cannot find the file specified." & _ "In the OpenDatabaseFile Function with " & _ FilePath & " Passed as a parameter." CASE 4 ' The system cannot open the file. Message$ = "The system cannot find the file specified." & _ "In the OpenDatabaseFile Function with " & _ FilePath & " Passed as a parameter." CASE ELSE RESUME NEXT END SELECT PRINT Message$ OpenDatabaseFile = Err END FUNCTION

You can be as detailed in your explanation of the error as you want. The important thing is that adequate information should be reported with the error to help correct it. If there's more than one thing that could happen in the process of performing an operation, you could write these errors to a log file so that all the details of the operation can be recorded and studied at a later time for possible correction. The CASE ELSE clause is telling the program that if any errors that aren't 2, 3 or 4 occurs, just continue with the normal execution of the code. I would say that the best thing to do is to use common sense and what you feel should be done. If you are using an application and you don't like the fact that the program stops everytime an insignificant error happens, then you need to assume that most people shouldn't like it if your program exits for the same reasons. Indeed a good way to learn is to see how other (popular and well known) programs handle their errors and to mimic them basically. If it's good enough for the others it should be good enough for your projects.

What can you learn from this? When you manage your errors, while you are coding (not adding error management to the project) the task doesn't look as bad and yet it requires the same amount of work. Usually, I have code snippets for all my error management situations and I just paste the appropriate code in the appropriate sub or function. Saves alot of typing and makes error management quite easy this way especially if the project is a big one. You can create standards this way that others can follow which also helps manage the overall quality of the whole project just by having a certain control over the errors that could occur even if the fault is that of the programmer.

AND IN CONCLUSION:

And this concludes our technique on proper error management. As you can see from the short code samples here, error management can represent a good part of the programming process. The more errors a sub or function needs to manage, the longer the error management part for that function or sub will be. And because that, you can imagine what a job it can be to add after you coded the program. It's doable but it's a big chunk of coding in itself if kept for the end of the programming phase.

Functions that perform calculations don't all need error management either. If you don't divide a variable by another in that function, you'll never cause a division by zero so that function can be spared the error management code. You have to take the time to see what the sub is doing, and what could go wrong when it does it's job. That's why common sense is of the essence. As always I'm opened to comments, suggestions and ideas about this document. Feel free to email me, as always, with any questions. Until I write again, have a good error free program.

MystikShadows
Stéphane Richard
srichard@adaworld.com