Handling Errors To Help You In Debugging - finding the source of your errors

free web hosting
Free Web Hosting > Computers & Tech > How-To's and Tutorials > Programming > C and C++

Handling Errors To Help You In Debugging - finding the source of your errors

mitchellmckain
One of the most important programming tasks is learning how to handle errors in a way that will be helpful to your debugging efforts. In today's programming we make extensive use of libraries and other code written by other people. When this code generates errors they can be rather hard to track down, since they usually generate exceptions which are caught out of your typical code sequence. In order to deal with this, I want to suggest three error handling ideas, that you can use without resorting to the disassembler.

The first is the use of checkpoints. These are regularly spaced points in your code where you store a unique code number in a static variable to keep track of where you are in the execution of your own code.

The second idea is to channel your response to all the errors you catch by various methods through a single code point. The reason is that with a single break point you can stop your program in time to trace the execution back to where the error was generated.

The third idea is to pass an origin code to subroutines which you make a large number of calls from numerous locations in your code. This is to help you immediately identify the location from which the subroutine was called. If you make a large enough number of calls to this routine, tracing back to exactly which call to it led to the error can be difficult.

It is a good idea to make this error code a seperate module, since it is something you can use in all of your projects. In this module you can make the header file something to include by other modules. In addition to your static checkpoint variable, you can define a macro which stores the checkpoint code and tests for errors. When an error is found you call the subroutine (error_break) which handles all of your errors according to the second idea above. Another useful item is a flag which tells your program whether to terminate on an error (user mode) or continue execution (debugging mode) for the purpose of tracing and error back to its source.

error.h
CODE

//Use this macro to check for errors while recording a checkpoint location
//test represents any additional local conditions under which to signal an error
#define checkpoint(test,j); {checkpointcode=j;if(test||errno==EDOM)error_break(j);}

extern bool exit_on_error;
extern int checkpoint;

void error_break(int j);

//you will also want to define any special exception types you might need here
//When you throw an exception you can throw anything at all: any integer, array, class, etc. in your program.
//So defining a seperate structure like this for an exception is optional.  However using a different structure
// for each type of exception makes your programming more readable and managable.  
struct specialException {
  int i,j,k;};
struct error_break_Exception {
  char buf[100];};


Now you can put the actual variables and subroutine code in the c++ file. You can also put in a _matherr routine to overrule the default handler.

error.cpp
CODE

// exit_on_error set to false causes the program to continue execution after an error
// use with breaks on the line below to trace the errors back to the source

  bool exit_on_error=false; //change this to true when you are finished debugging your program
  int checkpointcode=0;

//Since this file does not call error.h you need define here any exception types you use in this file
struct error_break_Exception {
  int j;};


//---------------------------------------------------------------------------
void error_break(int j){
       errbrkException e;
e.j=j;
//################################################################################
###
//******************put a break on the next line to cause program to halt when called
//################################################################################
###
       errno=0;
//here you can display error codes
//         store a whole list of error codes
//         throw an error_break_Exception under whatever conditions, for example
if(j>27){e.j=j;throw e;}
return;
}

//---------------------------------------------------------------------------
int _matherr (struct _exception *a){
//  In some case you may want to put code here to modifiy the return value without generating an error
//  For example acos and asin generate errors outside the range of -1 to 1.  Since it is easy to fall
//  outside of this range due to round off error you may simply want to return an appropriate value
//  rather than generate any kind of error.  This is accomplished by the following code.
   if(!strcmp(a->name,"acos")){
     if(a->arg1>1.0&&a->arg1<1.01){a->retval = 0.0;return 1;}
     if(a->arg1<-1.0&&a->arg1>-1.01){a->retval = M_PI;return 1;}}
   if(!strcmp(a->name,"asin")){
     if(a->arg1>1.0&&a->arg1<1.01){a->retval = M_PI_2;return 1;}
     if(a->arg1<-1.0&&a->arg1>-1.01){a->retval = - M_PI_2;return 1;}}

 error_break(9999);

//when you return from error_break you can examine the type, name and arguments of the error.
//...........................................................................
//a->type == DOMAIN Argument was not in domain of function, such as log(-1).
//a->type == SING Argument would result in a singularity, such as pow(0, -2).
//a->type == OVERFLOW Argument would produce a function result greater than DBL_MAX (or LDBL_MAX), such as exp(1000).
//a->type == UNDERFLOW  Argument would produce a function result less than DBL_MIN (or LDBL_MIN), such as exp(-1000).
//a->type == TLOSS Argument would produce function result with total loss of significant digits, such as sin(10e70).
//  You can check which math function generated the error by looking at a->name
//  You can check the arguments of the math function by looking at a->arg1 and a->arg2 (if 2 arguments)
//...........................................................................

 if(exit_on_error)return 0;
 return 1;  
}



In your main program you will use one or more try catch statement sets to catch error exceptions.

CODE

#include "error.h"
    ...
 
   //Using more than one try - catch set will also help you to identify what part of your code generated the error

      try {//your code, usually calls to subroutines and functions in your other modules
}      
      catch (error_break_Exception &e) {

 <code to display error message or information contained in e>

 //since this exception is generated by error_break itself, you do not call error break here.
        if(exit_on_error)exit_program(0);}
      catch (Exception &ex) {

 <code to display error message or information contained in ex>

        if(exit_on_error)exit_program(0);
        else errbrk(0);}

      catch (...) {
        //here is where you catch unknown exceptions types that may be thrown in libraries you use
 //You have no idea what informations was sent in the exception so you cannot display that
 // But you can display the checkpoint code that was saved at your last checkpoint.

   <code to display error message with last checkpoint code>

          if(exit_on_error)exit_program(0);
          else errbrk(0);}




Here is another method for catching errors defined in signal.h, which I have put in my error handling code.

Of course you need this at the top of your program.

CODE
 #include <signal.h>


Then you need to signal to install the signal handler at the beginning of you main program

CODE
signal(SIGFPE, (fptr)SignalSIGFPECatcher);


Add your signal handler prototype to error.h

CODE
  void SignalSIGFPECatcher(int *reglist);


Then you need to add your signal handler to error.cpp

CODE

//---------------------------------------------------------------------------
typedef void (*fptr)(int);
void SignalSIGFPECatcher(int *reglist){
  signal(SIGFPE, (fptr)SignalSIGFPECatcher);  //  ******reinstall signal handler

 error_break(9998);

  if(exit_on_error)_exit(1);
  else *(reglist + 8) = 3; /* make return AX = 3 */
}


The signal types that you can catch this way are as follows:
...........................................................................
SIGABRT Abnormal termination (default handler calls _exit(3))
SIGFPE Bad floating-point operation (default handler calls _exit(1))
Arithmetic error caused by
division by 0, invalid operation, etc.

SIGILL Illegal operation (default handler calls _exit(1))

SIGINT Control-C interrupt (default handler calls _exit(3))
SIGSEGV Invalid access to storage (default handler calls _exit(1))
SIGTERM Request for program termination (default handler calls _exit(1))
...........................................................................

 

 

 


Reply

mitchellmckain
On reveiwing this tutorial I noticed that one small explantion seems to have vanished. You are to use
CODE
#include "error.h"

in all of your other modules, so that you can use the checkpoint macro in them. Notice that you should not have this include statement in error.cpp itself.

Reply

mitchellmckain
I spotted a mistake in error.h
this line
CODE
struct error_break_Exception {
 char buf[100];};

should be
CODE
struct error_break_Exception {
 int j;};

in order to be consistent with error.cpp

Reply


Got an Opinion! Express your Views! (no registration):-
Add your Reply/ Opinion/ Views/ Comments/ Suggestion/ Questions/ Queries etc.
Posts with decent grammar & English will be accepted and please refrain from profanities.
For asking a Question, We recommend you to sign-up (for free) so that you can track the topic easily.

Nature of your Post*: Opinion/ Reply/ Comments
Question/Query
Feedback to us.
       
Name   Email
Title/Question*

(Maximum characters: 10,000)
You have characters left.


*RANDOM STUFF*





*SIMILAR VIDEOS*
Searching Video's for handling, errors, debugging, finding, source, errors
advertisement




Handling Errors To Help You In Debugging - finding the source of your errors



 

 

 

 

ADD REPLY / Got an Opinion! a humble request :-) RAPID SEARCH! Free Hosting [X]
Express your Opinions, Thoughts or Contribute your information that might help someone here.
Ask your Doubts & Queries to get answers.. "Together, We enlight each other!"
Register FREE for AD-FREE forum, Create your own topics, Ask Questions, track topics, setup subscriptions & notifications and Get a Free Website w/ Email and FTP.
500MB Space *No Ads*, CPanel, FTP, PHP, MySQL, EMails - 100% FREE