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.