8.5) Handling errors and exceptions in C

Handling errors and exceptions in C programs involves anticipating and managing unexpected situations that can arise during program execution.

C doesn’t have built-in exception handling like some other languages, but you can use various techniques to handle errors effectively. Let’s explore these techniques with explanations and examples:

Return Codes

Functions can return special values to indicate errors. Commonly used return codes include 0 for success and non-zero values for errors.

Example: Using Return Codes

#include <stdio.h>

int divide(int dividend, int divisor, int *result) {
    if (divisor == 0) {
        return 1; // Error code indicating division by zero
    }

    *result = dividend / divisor;
    return 0; // Success
}

int main() {
    int dividend = 10, divisor = 0, result;

    if (divide(dividend, divisor, &result) != 0) {
        printf("Error: Division by zero!\n");
    } else {
        printf("Result: %d\n", result);
    }

    return 0;
}

Output:

Error: Division by zero!

In this example, the divide function returns 1 to indicate an error (division by zero). The main function checks the return value to handle the error.

errno Variable

The errno variable is set by system calls and library functions to indicate specific errors. It’s part of the <errno.h> header.

Example: Using errno

#include <stdio.h>
#include <errno.h>

int main() {
    FILE *file = fopen("nonexistent_file.txt", "r");
    if (file == NULL) {
        printf("Error: %s\n", strerror(errno));
    } else {
        printf("File opened successfully!\n");
        fclose(file);
    }

    return 0;
}

Output:

Error: No such file or directory

In this example, the fopen function sets errno to indicate the error. The strerror function is used to convert the error number to a human-readable string.

assert Macro

The assert macro from <assert.h> checks an expression’s truthfulness. If the expression is false, the program terminates with an error message.

Example: Using assert

#include <stdio.h>
#include <assert.h>

int main() {
    int x = 5;
    assert(x == 10); // This assertion will fail

    printf("After assert\n");
    return 0;
}

Output (When Assertion Fails):

Assertion failed: (x == 10), function main, file example.c, line 7.
Abort trap: 6

In this example, the assert macro checks whether x is equal to 10, which is false, leading to program termination.

Custom Error Handling

You can define your own error handling functions to encapsulate error-related logic.

Example: Custom Error Handling

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

void handle_error(const char *message) {
    fprintf(stderr, "Error: %s\n", message);
    exit(1);
}

int main() {
    FILE *file = fopen("nonexistent_file.txt", "r");
    if (file == NULL) {
        handle_error("Failed to open file");
    } else {
        printf("File opened successfully!\n");
        fclose(file);
    }

    return 0;
}

Output:

Error: Failed to open file

In this example, the handle_error function is called when an error occurs. It prints the error message to stderr and exits the program.

Effective error handling is crucial for writing robust and reliable C programs. By using return codes, checking errno, employing assertions, and defining custom error handling functions, you can gracefully manage errors and exceptions in your programs.

Leave a Reply