w3resource

Comprehensive Guide to Error Handling in C: errno, perror(), and strerror()

Introduction to Error Handling in C

Overview:

In C programming, error handling is crucial for detecting and responding to errors in your programs. Tools like the errno variable and functions such as perror() and strerror() help in identifying and dealing with errors effectively.

Key Topics:

errno variable

The errno() is a global variable that stores error codes set by system calls and library functions when an error occurs. After a function returns an error (usually indicated by a return value like -1 or NULL), ‘errno’ can be checked to get the error code.

  • When to use: Use ‘errno’ after a system or library function returns an error (like -1 or NULL).
  • Why: To get the specific error code and handle it programmatically (e.g., for logging, retries, or specific error handling).

Example: Using errno to Check for Errors

Following example demonstrates how ‘errno’ is used to capture error codes when a function fails. Here, we try to open a non-existent file.

Code:

#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
    FILE *file;
    // Trying to open a non-existent file
    file = fopen("test11.txt", "r");
    // Check if the file failed to open
    if (file == NULL) {
        // Print the error number
        printf("Error Number: %d\n", errno);
        // Print the error description using strerror()
        printf("Error Description: %s\n", strerror(errno));
    }
    return 0;
}

Output:

Error Number: 2
Error Description: No such file or directory

Explanation:

  • This example demonstrates how ‘errno’ is used to capture error codes when a function fails. Here, we try to open a non-existent file.
  • 'errno' is set when an error occurs, and strerror() converts the error code to a readable message.
  • If fopen() fails, the error code is printed, and strerror(errno) provides a human-readable description of the error.

Example: Using errno with File operations

Code:

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

int main() {
    FILE *file;

    // Clear the current value of errno
    errno = 0;
    // Try to write to a file opened in read mode
    file = fopen("example.txt", "r");
    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }
    // Try writing to the file (this should cause an error)
    if (fputc('A', file) == EOF) {
        // Output the error description
        perror("Error writing to file");
    }
    // Close the file
    fclose(file);
    return 0;
}

Output:

Error writing to file: Bad file descriptor

Explanation:

  • In this example, we try to write to a file opened in read mode, which is not allowed.
  • fputc() fails, and ‘errno’ is set, triggering perror() to display the error: Error writing to file: Bad file descriptor.

perror() function

The perror() function prints a human-readable error message to stderr that corresponds to the value of 'errno'. When an error occurs, perror() can be used to display an error message alongside a custom message.

  • When to use: Use perror() right after an error occurs, particularly when you want to immediately display an error message to the user or developer.
  • Why: It provides a simple and quick way to output the error message associated with 'errno' for easier debugging.

Example: Using perror() for error Reporting

Code:

#include <stdio.h>
#include <errno.h>
int main() {
    FILE *file;
    // Trying to open a non-existent file
    file = fopen("test11.txt", "r");
    // Check if the file failed to open
    if (file == NULL) {
        // Use perror() to display a descriptive error message
        perror("Error opening file");
    }
    return 0;
}

Output:

>Error opening file: No such file or directory

Explanation:

  • perror() prints the specified message followed by the error description corresponding to the current value of 'errno'.
  • In this case, if the file can't be opened, perror() will output something like: Error opening file: No such file or directory.

strerror()function

The strerror() function returns a pointer to the error message string corresponding to the value of 'errno'. After an error, strerror(errno) can be used to get a textual description of the error code.

  • When to use: Use strerror() when we need the error message as a string (e.g., to store in a log file or return as part of an error message).
  • Why: It allows you to retrieve and manipulate the error message programmatically, rather than just printing it out. This is particularly useful in logging and custom error reporting systems.

Example: Combining strerror() and errno in Functions

Code:

#include <stdio.h>
#include <errno.h>
#include <string.h>
int divide(int a, int b) {
    if (b == 0) {
        errno = EDOM; // Set domain error (e.g., division by zero)
        return -1;
    }
    return a / b;
}
int main() {
    int result;
    result = divide(10, 0);
    if (result == -1) {
        // Use strerror() to describe the error
        printf("Division Error: %s\n", strerror(errno));
    }
    return 0;
}

Output:

Division Error: Domain error

Explanation:

  • This example illustrates how you can set 'errno' manually in custom functions.
  • When a division by zero occurs, 'errno' is set to EDOM, and the error is displayed using strerror().


Follow us on Facebook and Twitter for latest update.