Tutorials Logic, IN info@tutorialslogic.com
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Website Development
Practice
Quiz Challenge Interview Questions Certification Practice
Tools
Online Compiler JSON Formatter Regex Tester CSS Unit Converter Color Picker
Compiler Tools

C Error Handling errno, perror, strerror: Causes, Fixes, Examples & Interview Tips

Error Handling in C

Unlike C++ or Java, C has no built-in exception mechanism. Error handling in C is done through:

  • Return values - functions return a special value (e.g., -1, NULL, 0) to signal failure.
  • errno - a global integer variable set by system calls and library functions when an error occurs.
  • perror() - prints a human-readable error message to stderr.
  • strerror() - returns the error message string for a given errno value.

Return Value Pattern

The most fundamental C error handling pattern: check the return value of every function that can fail.

Checking Return Values
#include <stdio.h>
#include <stdlib.h>

// Function returns -1 on error, result on success
int divide(int a, int b, int *result) {
    if (b == 0) {
        return -1;  // error code
    }
    *result = a / b;
    return 0;  // success
}

int main() {
    int result;

    // Success case
    if (divide(10, 2, &result) == 0) {
        printf("10 / 2 = %d\n", result);
    } else {
        printf("Error: division failed\n");
    }

    // Error case
    if (divide(10, 0, &result) == 0) {
        printf("10 / 0 = %d\n", result);
    } else {
        printf("Error: cannot divide by zero\n");
    }

    // malloc returns NULL on failure
    int *arr = (int*)malloc(1000000000 * sizeof(int));  // huge allocation
    if (arr == NULL) {
        fprintf(stderr, "Error: memory allocation failed\n");
        return EXIT_FAILURE;
    }
    free(arr);

    return EXIT_SUCCESS;
}

errno, perror() and strerror()

errno is set by system calls when they fail. Always check errno immediately after a failed call - the next function call may overwrite it.

errno CodeValueMeaning
ENOENT2No such file or directory
EACCES13Permission denied
ENOMEM12Out of memory
EINVAL22Invalid argument
ERANGE34Result out of range
errno, perror() and strerror()
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

int main() {
    // Try to open a file that doesn't exist
    FILE *fp = fopen("nonexistent.txt", "r");

    if (fp == NULL) {
        // errno is set by fopen on failure
        printf("errno value: %d\n", errno);

        // perror: prints "prefix: error message" to stderr
        perror("fopen failed");

        // strerror: returns the error string
        printf("Error: %s\n", strerror(errno));
    }

    // Reset errno before next call
    errno = 0;

    // Math error: log of negative number
    #include <math.h>
    double result = sqrt(-1.0);
    if (errno == EDOM) {
        perror("sqrt(-1)");  // sqrt(-1): Numerical argument out of domain
    }

    return 0;
}

/*
Output:
errno value: 2
fopen failed: No such file or directory
Error: No such file or directory
*/

Custom Error Handling Pattern

A clean pattern for larger programs: define your own error codes and a centralized error handler.

Custom Error Codes Pattern
#include <stdio.h>
#include <stdlib.h>

// Custom error codes
typedef enum {
    ERR_OK       = 0,
    ERR_NULL_PTR = 1,
    ERR_DIV_ZERO = 2,
    ERR_OVERFLOW = 3,
    ERR_IO       = 4
} ErrorCode;

// Error message lookup
const char* errorMessage(ErrorCode code) {
    switch (code) {
        case ERR_OK:       return "Success";
        case ERR_NULL_PTR: return "Null pointer";
        case ERR_DIV_ZERO: return "Division by zero";
        case ERR_OVERFLOW: return "Integer overflow";
        case ERR_IO:       return "I/O error";
        default:           return "Unknown error";
    }
}

// Function using custom error codes
ErrorCode safeDivide(int a, int b, int *out) {
    if (out == NULL) return ERR_NULL_PTR;
    if (b == 0)      return ERR_DIV_ZERO;
    *out = a / b;
    return ERR_OK;
}

int main() {
    int result;
    ErrorCode err;

    err = safeDivide(10, 2, &result);
    if (err == ERR_OK) printf("10/2 = %d\n", result);
    else printf("Error: %s\n", errorMessage(err));

    err = safeDivide(10, 0, &result);
    if (err == ERR_OK) printf("10/0 = %d\n", result);
    else printf("Error: %s\n", errorMessage(err));  // Error: Division by zero

    err = safeDivide(10, 2, NULL);
    if (err == ERR_OK) printf("result = %d\n", result);
    else printf("Error: %s\n", errorMessage(err));  // Error: Null pointer

    return 0;
}

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.