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 9:56

>>2
i'm now working on pthread aware implementation of exceptions
looks good so far, it will have to use thread specific data for this and as i have a bit more to put to it the result will, no doubt, be intresting as i want to have universal code usable in other projects

yes call/cc is reentrant, i didn't know it's threadsafe though... care to point me to an example implementation?

>>5
real life application? it's hard not to use exceptions IRL programming and the applications are numerus but complex and hard to summarize in a simple BBS post (network communication and database interaction are places where it's most useful)

but consider this example:
there's a function that returns integers (both negative and positive) and accepts two arguments
let's say that one of those two arguments have to be smaller than some value and second one bigger than some value

we can't use a special return (either negative or positive) as the functions returns them in normal operation, and we can't use 0, as we have two different situations

with exceptions we can throw exception nr 1 from inside of this function if the first value is too big and a exception nr 2 if the second is too small

in exception handling we can inform user that either this one or that one argument to function is too big

and then in finally block free memory, close db connections etc.

you can, of course, check it before calling the function, but if you take into cosideration that you call the function from multiple places and that the code is written by few people, then it's ineffective and error prone

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