C errno.h Header
Error handling and reporting functions
⚠️ What is errno.h?
The errno.h header provides error handling capabilities through the errno variable and related functions. It helps identify and handle errors that occur during program execution, especially with system calls and library functions.
#include <errno.h>
int main() {
FILE *file = fopen("nonexistent.txt", "r");
if (file == NULL) {
printf("Error code: %d\n", errno);
perror("File error");
}
return 0;
}
Sample Output:
Error code: 2 File error: No such file or directory
Key errno.h Features
errno
Global variable storing error codes
if (errno != 0) { ... }
perror()
Print error message to stderr
perror("Error occurred");
strerror()
Get error message string
char *msg = strerror(errno);
Error Codes
Predefined error constants
ENOENT, EACCES, ENOMEM
🔹 Basic Error Handling
Detecting and handling errors in file operations prevents data loss, ensures program reliability, and provides meaningful feedback to users. Always check return values from functions like fopen(), fread(), and fwrite() for NULL or error indicators. The global errno variable provides specific error information. Implement cleanup routines ensuring files close properly and allocated memory is freed. Robust error handling transforms unpredictable failures into controlled, manageable situations. Professional programs implement comprehensive error detection and recovery strategies.
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
FILE *file;
// Reset errno before operation
errno = 0;
// Try to open a file that doesn't exist
file = fopen("missing_file.txt", "r");
if (file == NULL) {
printf("Failed to open file!\n");
printf("Error number: %d\n", errno);
printf("Error message: %s\n", strerror(errno));
// Alternative: use perror()
perror("fopen");
return 1; // Exit with error code
}
printf("File opened successfully!\n");
fclose(file);
return 0;
}
Output:
Failed to open file! Error number: 2 Error message: No such file or directory fopen: No such file or directory
🔹 Common Error Codes
Understanding different error types including ENOENT, EACCES, and ENOSPC helps diagnose and respond appropriately to various failure conditions in C. Error codes from errno.h provide specific information about what went wrong. ENOENT indicates missing files, EACCES represents permission denied, ENOSPC means insufficient storage. The perror() function displays human-readable error messages. Learning error codes enables you to implement targeted recovery strategies. Comprehensive error understanding significantly improves application reliability and user experience.
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
void demonstrate_error(int error_code, const char* description) {
errno = error_code;
printf("Error %d (%s): %s\n", error_code, description, strerror(errno));
}
int main() {
printf("Common Error Codes:\n\n");
// Simulate different error conditions
demonstrate_error(ENOENT, "ENOENT"); // No such file or directory
demonstrate_error(EACCES, "EACCES"); // Permission denied
demonstrate_error(ENOMEM, "ENOMEM"); // Out of memory
demonstrate_error(EINVAL, "EINVAL"); // Invalid argument
demonstrate_error(EIO, "EIO"); // I/O error
// Example: Memory allocation failure simulation
printf("\nMemory allocation example:\n");
errno = 0;
// This won't actually fail on most systems, but demonstrates the concept
void *ptr = malloc(SIZE_MAX);
if (ptr == NULL && errno != 0) {
printf("malloc failed: %s\n", strerror(errno));
} else {
printf("malloc succeeded (or errno not set)\n");
if (ptr) free(ptr);
}
return 0;
}
Sample Output:
Common Error Codes: Error 2 (ENOENT): No such file or directory Error 13 (EACCES): Permission denied Error 12 (ENOMEM): Cannot allocate memory Error 22 (EINVAL): Invalid argument Error 5 (EIO): Input/output error Memory allocation example: malloc succeeded (or errno not set)
🔹 Error Handling Best Practices
Proper error checking and cleanup procedures prevent resource leaks, data corruption, and ensure graceful failure recovery in production C applications. Always validate function return values and check for NULL pointers before dereferencing. Implement cleanup code ensuring files close and memory releases even when errors occur. Use goto statements strategically for centralized error handling or implement cleanup functions. Document expected error conditions and implement appropriate recovery mechanisms. These practices transform robust error handling into standard programming practice.
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
int safe_file_copy(const char *source, const char *dest) {
FILE *src = NULL, *dst = NULL;
char buffer[1024];
size_t bytes;
int result = 0;
// Clear errno before starting
errno = 0;
// Open source file
src = fopen(source, "rb");
if (src == NULL) {
fprintf(stderr, "Cannot open source file '%s': %s\n",
source, strerror(errno));
return -1;
}
// Open destination file
dst = fopen(dest, "wb");
if (dst == NULL) {
fprintf(stderr, "Cannot create destination file '%s': %s\n",
dest, strerror(errno));
result = -1;
goto cleanup;
}
// Copy file contents
while ((bytes = fread(buffer, 1, sizeof(buffer), src)) > 0) {
if (fwrite(buffer, 1, bytes, dst) != bytes) {
fprintf(stderr, "Write error: %s\n", strerror(errno));
result = -1;
goto cleanup;
}
}
// Check for read errors
if (ferror(src)) {
fprintf(stderr, "Read error: %s\n", strerror(errno));
result = -1;
}
cleanup:
if (src) fclose(src);
if (dst) fclose(dst);
return result;
}
int main() {
if (safe_file_copy("source.txt", "destination.txt") == 0) {
printf("File copied successfully!\n");
} else {
printf("File copy failed!\n");
}
return 0;
}
Sample Output (if source.txt doesn't exist):
Cannot open source file 'source.txt': No such file or directory File copy failed!