Custom Errors in C

Our first example demonstrates how to create custom error types in C. This is achieved by implementing a struct that represents the error and functions to create and handle these custom errors.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// A custom error type usually has the suffix "Error".
typedef struct {
    int arg;
    char* message;
} ArgError;

// Function to create a new ArgError
ArgError* new_arg_error(int arg, const char* message) {
    ArgError* error = malloc(sizeof(ArgError));
    error->arg = arg;
    error->message = strdup(message);
    return error;
}

// Function to free an ArgError
void free_arg_error(ArgError* error) {
    free(error->message);
    free(error);
}

// Function to get the error message
char* arg_error_message(ArgError* error) {
    char* result = malloc(100);
    snprintf(result, 100, "%d - %s", error->arg, error->message);
    return result;
}

// Our example function that might return an error
int f(int arg, ArgError** error) {
    if (arg == 42) {
        // Return our custom error
        *error = new_arg_error(arg, "can't work with it");
        return -1;
    }
    return arg + 3;
}

int main() {
    ArgError* error = NULL;
    int result = f(42, &error);
    
    if (error != NULL) {
        char* message = arg_error_message(error);
        printf("%s\n", message);
        free(message);
        free_arg_error(error);
    } else {
        printf("Result: %d\n", result);
    }

    return 0;
}

In this C version, we’ve created a struct ArgError to represent our custom error type. We’ve also implemented functions to create, free, and get the message from an ArgError.

The f function now takes a pointer to an ArgError pointer as its second argument. If an error occurs, it sets this pointer to a newly created ArgError.

In the main function, we check if an error occurred by seeing if the error pointer is not NULL. If it’s not NULL, we print the error message and free the error. Otherwise, we print the result.

To run this program:

$ gcc custom_errors.c -o custom_errors
$ ./custom_errors
42 - can't work with it

This example demonstrates how to implement and use custom error types in C. While C doesn’t have built-in error handling mechanisms like some higher-level languages, we can still create structured error handling systems using structs and pointers.