Table of Contents

C goto error handling

C goto error handling uses goto labels to centralize cleanup code, avoiding nested error handling and ensuring resources are freed consistently. Each operation jumps to the appropriate cleanup label on error, executing only the necessary cleanup steps in reverse order.

Use goto error_label: in C to handle cleanup elegantly without repetition or deeply nested conditionals.

Example

This example shows goto for resource cleanup with proper unwinding.

// compile: gcc -o goto_error goto_error.c
// run: ./goto_error
// description: error handling with goto for cleanup
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
typedef struct {
    FILE *f;
    int *buffer;
} Resources;
 
int read_config(const char *filename, Resources *res) {
    memset(res, 0, sizeof(*res));
 
    // Open file
    res->f = fopen(filename, "r");
    if (res->f == NULL) {
        fprintf(stderr, "Failed to open %s\n", filename);
        goto error;
    }
 
    // Allocate buffer
    res->buffer = malloc(1024 * sizeof(int));
    if (res->buffer == NULL) {
        fprintf(stderr, "Failed to allocate buffer\n");
        goto error_close_file;
    }
 
    // Read data
    int count = fread(res->buffer, sizeof(int), 100, res->f);
    if (count != 100) {
        fprintf(stderr, "Failed to read data\n");
        goto error_free_buffer;
    }
 
    return 0;  // Success
 
    // Error handling with cleanup
error_free_buffer:
    free(res->buffer);
    res->buffer = NULL;
error_close_file:
    fclose(res->f);
    res->f = NULL;
error:
    return -1;
}
 
void cleanup(Resources *res) {
    if (res->buffer != NULL) {
        free(res->buffer);
        res->buffer = NULL;
    }
    if (res->f != NULL) {
        fclose(res->f);
        res->f = NULL;
    }
}
 
int main() {
    Resources res;
 
    // Try to read config
    if (read_config("nonexistent.dat", &res) != 0) {
        printf("Failed to read config\n");
        cleanup(&res);
        return 1;
    }
 
    printf("Config read successfully\n");
    cleanup(&res);
    return 0;
}

Common patterns

Error path organization:

Naming convention:

Comparison with alternatives:

Resource management:

Scope alternatives (if available):

Best practices:

Avoiding goto for non-error control:

Error propagation:

Modern C patterns: