A good use of goto for error handling

Not all use of goto is considered evil by C programmers. Used appropriately, it can make code easier to read, and increase code performance.

It is often you have a series of mallocs.


static char *a, *b, *c, *d;
void do_initialization(void)
{
a=malloc(10);
b=malloc(10);
c=malloc(10);
d=malloc(10);
}

To be robus, each malloc should be checked for failure. The do_initialization should reflect either success or failure. The following code implements that, but introduces more bugs.


int do_initialization()
{
if ((a = malloc(10)) == NULL) return -1;
if ((b = malloc(10)) == NULL) return -1;
if ((c = malloc(10)) == NULL) return -1;
if ((d = malloc(10)) == NULL) return -1;
return 0;
}

Memory leaks have been introduced. Lets fix that.


int do_initializae()
{
if ((a = malloc(10)) == NULL) return -1;
if ((b = malloc(10)) == NULL) {
free(a);
return -1;
}
if ((c = malloc(10)) == NULL) {
free(b);
free(a);
return -1;
}
if ((d = malloc(10)) == NULL) {
free(c);
free(b);
free(a);
}
return 0;
}

That correctly implements do_initialization, but it appears somewhat redundant and can be hard to read in larger projects.

A good use of goto can make the above code much better.


int do_initialization()
{
if ((a = malloc(10)) == NULL) return -1;
if ((b = malloc(10)) == NULL) goto err_a;
if ((c = malloc(10)) == NULL) goto err_b;
if ((d = malloc(10)) == NULL) goto err_c;
return 0;
err_c: free(c);
err_b: free(b);
err_a: free(a);
return -1;
}
The code demonstrated above is very often seen in production code. The opensource kernels and other large C projects, make extensive use of this type of construct.

One response to “A good use of goto for error handling

  1. I use the following approach which I think is clearer, more easily extensible and maintainable because it only uses one label:

    p1=p2=…=pN=NULL;
    if (NULL == (p1=malloc(…))) goto cleanup;

    if (NULL == (pN=malloc(…))) goto cleanup;
    return 0;
    cleanup:;
    if (NULL != p1) free(p1);

    if (NULL != pN-1) free(pN-1);
    return -1;

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s