C - Error Handling

C doesn’t have exceptions; use return codes, errno, and defensive checks to handle errors.

Learning Objectives

  • Check return values and use errno with perror/strerror.
  • Perform robust input validation and resource cleanup.

Return codes and errno

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

int main(void) {
  FILE *fp = fopen("missing.txt", "r");
  if (!fp) {
    perror("fopen failed");          // prints reason based on errno
    fprintf(stderr, "error: %s\n", strerror(errno));
    return 1;
  }
  fclose(fp);
}

Validation and cleanup

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

int process(const char *path) {
  FILE *fp = fopen(path, "r");
  if (!fp) return -1;
  char *buf = malloc(1024);
  if (!buf) { fclose(fp); return -2; }
  // ... use fp and buf ...
  free(buf); fclose(fp); return 0;
}

Common Pitfalls

  • Ignoring function return values.
  • Using uninitialized memory or freed pointers after an error.
  • Leaking resources when taking early returns.