ProgrammingBackend C Developer

How to implement error handling when working with the C standard library functions? What is the specificity of using errno, when is it better to use return codes, and how to avoid errors in handling?

Pass interviews with Hintsage AI assistant

Answer.

Background

Error handling in C has always been the developer's responsibility. The standard library does not have exceptions; errors are returned via return codes or the global variable errno (first used in UNIX in the 1970s, then POSIX and ANSI C). Such mechanisms are still used today to manage the flow of execution in non-standard situations.

The Problem

Errors when working with standard functions (file operations, memory allocation, string functions) can be unnoticed without special control. Incorrect handling — ignoring the return code, misinterpreting errno, failure to release resources — leads to incorrect program behavior, crashes, and vulnerabilities.

The Solution

Proper error handling requires mandatory analysis of values returned by functions, using errno only immediately after a failure, and providing informative error outputs. Return codes are preferred for internal functions — they allow for handling without global side effects. errno is more often used with system calls and standard library functions. After each potentially harmful operation, the return is analyzed, and the global state (errno) should not be overwritten by intermediate calls.

Code Example:

#include <stdio.h> #include <errno.h> #include <string.h> FILE *open_file(const char *filename) { errno = 0; FILE *f = fopen(filename, "r"); if (!f) { fprintf(stderr, "Error: %s ", strerror(errno)); } return f; }

Key Features:

  • errno is used only for diagnosing errors that occur in system calls/standard functions.
  • It is convenient to return int error codes inside functions, where zero indicates success, negative numbers or special values indicate failure.
  • It is important not to rely on the value of errno if there hasn’t been an error before.

Trick Questions.

Can errno be used for user-defined functions if you want to propagate errors upwards?

No, errno is intended only for standard library and system calls. It is global, can be overwritten at any point, and is unsuitable for your own functions.

Is it necessary to set errno before every function call?

No, but it is recommended to reset errno (e.g., to zero) before calls if you plan to analyze changes. Not every function changes errno on success, only on error.

errno = 0; ... call dangerous function ...

Can errno be trusted after any function?

Only for those functions that, according to the standard, explicitly set it on failure. Many standard library functions do not touch errno on success. Documentation is your friend.

Common Mistakes and Anti-Patterns

  • Ignoring return codes from functions (e.g., fopen, malloc, write).
  • Overwriting errno before using its value.
  • Using errno for your own errors in a project.

Real-life Example

Negative Case

Opening a file without checking the result, errors are not analyzed, the program behaves incorrectly when the file is missing:

Pros:

  • Less code, works quickly in simple scenarios.

Cons:

  • Cryptic failures on errors, diagnostic impossibility.

Positive Case

After each critical function, the result is checked; in case of an error, a detailed message with strerror(errno) is output, execution correctly terminates:

Pros:

  • The program is easy to maintain and debug, with high stability.

Cons:

  • Slightly more code, a bit higher complexity.