Flow controlling macros with 'goto'

Error handling is one of the rare situations when goto is not so bad.

But if I had to maintain that code I would be very upset that goto are hidden by macros.

So in this case goto is OK for me but not macros.


Using goto to go to a common error handler/cleanup/exit sequence is absolutely fine.


This code:

void func()
{
   char* p1 = malloc(16);
   if( !p1 )
      goto cleanup;

   char* p2 = malloc(16);
   if( !p2 )
      goto cleanup;

 cleanup:

   if( p1 )
      free(p1);

   if( p2 )
      free(p2);
}

can be legally written as:

void func()
{
   char* p1 = malloc(16);
   char* p2 = malloc(16);

    free(p1);
    free(p2);
}

whether or not the memory allocations succeed.

This works because free() does nothing if passed a NULL pointer. You can use the same idiom when designing your own APIs to allocate and free other resources:

// return handle to new Foo resource, or 0 if allocation failed
FOO_HANDLE AllocFoo();

// release Foo indicated by handle, - do nothing if handle is 0
void ReleaseFoo( FOO_HANDLE h );

Designing APIs like this can considerably simplify resource management.