Computers for children

From: George Currie <g_at_kurico.com>
Date: Sat Jan 16 15:19:33 1999

I often will use the following:

#define ERRIF(cond,target) if (cond) goto target
#define ERRHANDLER(target) target:

and you would use it like so:

while (looper) {
   do stuff;
   ERRIF(readData,ERROR_DATAREAD);
   do more stuff;
   }

return SUCCESS;

ERRHANDLER(ERROR_DATAREAD)
   closeFile();
   do some other cleanup
   return RC_DATAREAD;


An interesting way to use it is as follows:

ERRIF(openFile(),ERROR_OPENFILE);
ERRIF(allocMem(),ERROR_ALLOCMEM);
ERRIF(readFile(),ERROR_READ);
closeFile(); // yeah I know
return SUCCESS;

ERRHANDLER(ERROR_READ)
   freeMem(); // free the buffer, now this will fall
                      //through to close the file

ERRHANDLER(ERROR_ALLOCMEM)
   closeFile();

ERRHANLDER(ERROR_OPENFILE)
   return RC_ERROR;

This is a simplified view (the macros I have are quite extensive), but
you get the idea. I find this to be a very intuitive (of course since I
made it up) and useful. There are still a few situations it doesn't
handle well but it really helps, esp. avoiding the forever nested
tests for errors.

George

> It was thus said that the Great Uncle Roger once stated:
> >
> > >and while loops (I rarely use for's), but C really suffers from a lack
> > >of a general error trapping mechanism that one can invoke to break out
> > >of loops as required. Sometimes I think goto's are the answer but I
> > >can never find an appropriate way to implement it.
> >
> > errflag := 0 /* is it := in C to assign a value? */
>
> No, it's a simple `='. Comparrisons are done using `=='.
>
> > DO WHILE variable < end AND errflag = 0 {
> > do stuff
> > variable++ /* I think that increments a variable */
> > IF error THEN
> > errflag := 1
> > ENDIF
> > LOOP
> >
> > IF errflag = 1 THEN
> > do error processing
> > ENDIF
>
> C does include a `break' keyword, which breaks out of an enclosing
> `while', `do' or `for' loop, but it has limited scope:
>
> while(a)
> {
> while(b)
> {
> break; /* break out of b */
> }
> /* still stuck here in a */
> }
>
> And if it's an error condition, you often have to set a flag to be
> tested
> outside the loop anyway:
>
> while(a)
> {
> rc = processing();
> if (rc == ERROR) break;
> if (rc == DONE) a = FALSE;
> }
>
> if (rc == ERROR) /* handle error */
> {
> }
>
> It takes quite a bit of thought to avoid this double testing (as I call
> it). One way would be to move the error handling code to where you detect
> the error and then break out fo the loop:
>
> while(a)
> {
> rc = processing();
> if (rc == ERROR)
> {
> /* handle error */
> break;
> }
> if (rc == DONE) a = FALSE;
> }
>
> Another way is to write code such that errors can only happen in limited
> areas. For instance, in C, to allocate memory, you typically do:
>
> p = malloc(SOMESPACE);
> if (p == NULL)
> {
> /* handle out of memory error */
> }
>
> I wrote a wrapper function MemAlloc() that calls malloc(), but if
> there's
> no memory, aborts the program (default case, you can override that
> behavior if need be), otherwise returns the memory. So I know that all my
> calls to MemAlloc() will succeed (because it never returns if it fails).
>
> Over the past year I've developed what amounts to an exception mechanism
> for C that's fairly decent (given the constraints I have to work with), so
> it can be done, you just need to be a bit creative when it comes to
> coding.
>
> -spc (I've also done templates in C, but that's another story ... )
>
Received on Sat Jan 16 1999 - 15:19:33 GMT

This archive was generated by hypermail 2.3.0 : Fri Oct 10 2014 - 23:32:06 BST