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:
Table of Contents
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.