GO
home account info subscribe login search FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
[an error occurred while processing this directive]
Previous Table of Contents Next


Technique

Another way to handle error conditions in your code is to perform what are known as non-local jumps. This means if an error occurs in a function, you can jump to a particular line of code. Typically, that line of code is just prior to where the function was originally called.

Using the setjmp and longjmp functions provided with the Standard C Library, you can perform non-local jumps to handle error conditions and still maintain the state of the caller’s stack environment. This means when control is set back to the calling function, its local variables still have the same values.

This How-To will discuss how to use setjmp and longjmp together to perform error handling. This How-To will also discuss how they work and why it is not safe to use these functions in C++ programs.

Steps

1.  Include stdio.h for standard I/O operations.
#include <stdio.h>
2.  Include setjmp.h for the setjmp and longjmp functions and the jmp_buf typedef.
#include <setjmp.h>
3.  Define the prototype for a function that you will call from main.
void DoSomeWork(void);
4.  Define a global jump buffer environment variable using the jmp_buf typedef.
jmp_buf Env;
5.  Inside main, call setjmp to record the stack environment. Then call the function defined in step 3.
void main()
{
   int retVal = setjmp(Env);

   if (retVal != 0)
      printf(“Call to setjmp returned: %d\n”, retVal);
   else
      DoSomeWork();
}
6.  Implement the DoSomeWork function. This function attempts to open a file that does not exist. If the open fails, it calls longjmp to cause the program to return from the call to setjmp again.
void DoSomeWork(void)
{
   FILE* fptr = fopen(“NoSuchFile”, “r”);

   if (fptr == NULL)
   {
      printf(“Calling longjmp\n”);
      longjmp(Env, -1);
   }
}

How It Works

The setjmp function records the current state of the stack environment. The jmp_buf typedef is an implementation-defined array. After recording the current stack environment, setjmp returns 0.

A call to longjmp will restore the stack environment that was saved when setjmp was called. When calling longjmp, you specify the variable used to save the stack environment and a return code. Calling longjmp causes the program to return from setjmp, again returning the return code that was given to longjmp as the second parameter. When setjmp returns, all variables, except register variables, that are accessible by the function calling setjmp have the same values they had when the longjmp function was called.

The sample code in the preceding “Steps” section first calls setjmp to save the current state. The return value from this first call to setjmp is 0, so you call the DoSomeWork function. This function attempts to open a file that does not exist. If the open fails, DoSomeWork calls longjmp and passes to it the stack environment previously saved and a return code of -1. This causes setjmp to be returned from again. This time the return value from setjmp is -1. Therefore, the program exits.

Comments

Using setjmp and longjmp, you can implement another form of error handling in your programs. However, you should not use setjmp and longjmp in C++ programs. These functions do not support the semantics of C++ objects. That means destructors for objects will not be called when longjmp is called. In C++ programs, you should use the C++ exception-handling constructs that are talked about in Chapter 11, “Exception Handling in C++.

10.9 Use a C++ class to handle runtime errors in a more maintainable fashion?

Problem

I understand the importance of error handling in my programs. I also understand how to return values from functions. Is there a better way to keep track of error information in my programs?

Technique

Returning error values from functions is a very efficient way to handle errors. However, the meanings of the return values of many different functions can be very difficult to keep track of. They are also very difficult to maintain, especially if you are not the original developer of the code and the comments are poorly written or nonexistent.

This section provides a sample class called ErrorClass that can be used as the return value for a function. This class takes care of maintaining error codes and provides human-readable descriptions. You can then modify this class to suit your own needs.

Steps

This section discusses how to use this sample class in your programs. The actual class itself will be discussed in the “How It Works” section.

1.  Create a file that contains descriptions of all the errors you will encounter in your program. Here is an example of an error file called errors.txt.
Error opening file
Error reading file
Floating-point exception
Unable to open database
Database query failed
Drive is full
Web page not found
2.  Create a header file that contains macros for your error codes. Here is an example of a header file that holds all the error codes for a program. You should name this file errors.h.
#define OPNERR      0  // Error opening file
#define READERR     1  // Error reading file
#define FPERR       2  // Floating-point exception
#define DBOPNERR    3  // Unable to open database
#define DBQERR      4  // Database query failed
#define DRVFULLERR  5  // Drive is full
3.  Create a global instance of the ErrorClass class.
ErrorClass ec;
4.  When your program starts, load the description of your errors from an error file. If loading the errors fails, you might want to exit the program.
if (ec.loadErrors(ERROR_FILE) == false)
{
   cout << “Error loading error file” << endl;
   exit(-1);
}
5.  When an errors in a function, set the current error code.
ec.currentError(OPNERR);


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.