Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Exceptions in C

Name: Anonymous 2008-06-14 8:02

i made an exception handling header for C and thought /prog/ could find a use for it, anyway, enjoy:
(simple usage below)

exception.h
/**
 * exception handling for ANSI C
 * \note NOT thread-safe \br
 * values of automatic variables are unspecified (look to longjmp(3) man page)
 */
#ifndef __EXCEPTION_H
#define __EXCEPTION_H

/// programmer can declare this to achive deeper recursion
#ifndef __EXMAXNEST
#       define __EXMAXNEST 16
#endif
/// simple stack for environment buffers used by setjmp()
jmp_buf  __exbuf[__EXMAXNEST];
/// simple stack for exit values of longjmp()
int      __exvalue[__EXMAXNEST];
/**
 * simple stack to check if current exception has been handled
 * (needed for upward propagation)
 */
char     __exhandled[__EXMAXNEST];
/// simple stack pointer
int      __exnest = 0;

/// try block
#define try      {                                                           \
                    if(__exnest >=  __EXMAXNEST) {                           \
                        fprintf(stderr, "%s:%i: Too deep try (...) catch "   \
                                "recursion. Aborting... \n", __FILE__,       \
                                __LINE__);                                   \
                        abort();                                             \
                    }                                                        \
                    __exhandled[__exnest] = 0;                               \
                    if ((__exvalue[__exnest] =                               \
                         setjmp(__exbuf[__exnest++])) == 0) {
/// catch block
#define catch(x)    } else if (__exvalue[__exnest-1] == (x) ) {              \
                        __exhandled[__exnest-1] = 1;                         \
                        --__exnest;
/**
 * finally block
 * \note must be always included, even if no code goes into finally block
 */
#define finally     } else {                                                 \
                        __exhandled[__exnest-1] = 0;                         \
                        --__exnest;                                          \
                    }
/// closing part for try block
#define end_try     if( __exhandled[__exnest] == 0)                          \
                        if (__exnest != 0) {                                 \
                            longjmp(__exbuf[__exnest-1],                     \
                                    __exvalue[__exnest]);                    \
                        } else {                                             \
                            fprintf(stderr, "%s:%i: Unhandled "              \
                                    "exception %i. Aborting...\n",           \
                                    __FILE__,  __LINE__,                     \
                                    __exvalue[__exnest]);                    \
                            abort();                                         \
                        }                                                    \
                }
/// throws exception given as a parameter
#define throw(x)    longjmp(__exbuf[__exnest-1], (x))
/**
 * makes current exception unhandled (it will be propagated upwards), useful
 * to just print debug mesages from local variables and continue
 * unvinding the stack
 * \note can be safely used only in catch() block
 */
#define unhandled   __exhandled[__exnest] = 0
/**
 * does basically the same thing as unhandled but can
 * change exception type, better that throw in catch() because it doesn't make
 * the finally block unexecuted
 * \note can be safely used only in catch() block
 */
#define rethrow(x)  __exhandled[__exnest] = 0;                               \
                    __exvalue[__exnest] = (x)

#else

extern jmp_buf  __exbuf[__EXMAXNEST];
extern int      __exvalue[__EXMAXNEST];
extern char     __exhandled[__EXMAXNEST];
extern int      __exnest;

#endif


usage:
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include "exception.h"

int func(int a)
{
        throw(1);
}

int main(int argc, char** argv)
{
        try
                func(2);
        catch(2)
                printf("exception catched\n");
        catch(1)
                printf("weird exception, make it unhandled\n");
                unhandled;
        finally
                printf("always executed\n");
        end_try

        exit(0);
}

Name: Anonymous 2008-06-14 10:16

>>5
Traditionally, error notification and handling is done by one of two methods.

One is to use a special return code in your function that indicates an error occurred, and then use an auxiliary function or value to determine the type of error. For example, C's errno or Win32's GetLastError().

The other is to jump to another specified location in your program whenever an error condition is detected. For example, BASIC's ON ERROR GOTO or DOS batch language's IF ERRORLEVEL ... GOTO.

Exception handling differs from these in that it tries to provide a neater structure for handling errors. You no longer have to use an arbitrary return code to indicate error, and you don't have to jump somewhere else in your program or calling function - the error handling code is always in a certain defined block.

For example, here's how you might open a file with exception handling (in pseudocode):

  try:
    f = open(filename)
  catch FileNotFound:
    print "cannot find "+filename
  catch AccessDenied:
    print "no permission to open "+filename
  except:
    print "unknown error number "+error+" opening "+filename


Note the neat way in which error handling code is separated out into different blocks depending on which error they are handling.

Here's the equivalent using the first two methods. The first is a mangled mess of if statements, and the second is spaghetti code:

  f = open(filename)
  if (f equals 0):
    if (error equals 2):
      print "cannot find "+filename
    elseif (error equals 5):
      print "no permission to open "+filename
    else:
      print "unknown error number "+error+" opening "+filename
    endif
  endif


  on error goto fileopenerrorhandler
  f = open(filename)
 
  (.. other stuff ..)

  fileopenerrorhandler:
    if (f equals 0):
      if (error equals 2):
        print "cannot find "+filename
      elseif (error equals 5):
        print "no permission to open "+filename
      else:
        print "unknown error number "+error+" opening "+filename
      endif
    endif

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List