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.
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; }
Error path organization:
Naming convention:
error_resource_name:: clear what's cleaned uperror:: final fallback cleanupComparison with alternatives:
Resource management:
Scope alternatives (if available):
__exit__ cleanupBest practices:
Avoiding goto for non-error control:
goto for error handling: accepted and idiomatic in Cgoto for loops/jumps: confusing, use loops insteadError propagation:
Modern C patterns:
__attribute__((cleanup)) (GCC) to auto-cleanup