C Error Handling

⚠️ C Error Handling
Unlike some modern languages, C does not have built-in exception handling (like try-catch).
Instead, C uses several alternative mechanisms for detecting and managing errors manually.
🔹 Methods of Error Handling in C
| Method | Used For |
|---|---|
| Return values | Function failure signals |
errno | Global error reporting |
perror() / strerror() | Human-readable error messages |
Assertions (assert) | Debugging and sanity checks |
setjmp() / longjmp() | Manual exception-like behavior |
1. Error Handling using Return Values
Functions often return special values like -1, NULL, or 0 to indicate failure.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <stdio.h> int divide(int a, int b) { if (b == 0) return -1; // error return a / b; } int main() { int res = divide(10, 0); if (res == -1) printf("Error: Division by zero!\n"); else printf("Result = %d\n", res); return 0; } |
2. Error Handling Using errno
errno is a global variable set by some library functions when an error occurs.
Include:
#include <errno.h>
#include <string.h>
#include <stdio.h>
Example:
1 2 3 4 5 6 7 8 9 10 11 | #include <stdio.h> #include <errno.h> #include <string.h>int main() { FILE *f = fopen("missing.txt", "r"); if (f == NULL) { printf("Error: %s\n", strerror(errno)); } return 0; } |
3. perror() and strerror()
| Function | Purpose |
|---|---|
perror("message") | Prints a system error message with context |
strerror(errno) | Returns error message as a string |
Example:
1 2 3 4 5 | FILE *f = fopen("data.txt", "r"); if (!f) { perror("File open failed"); } |
Output example:
File open failed: No such file or directory
4. Using assert() (Debugging Only)
Stops the program if a condition is false.
1 2 3 4 5 6 7 | #include <assert.h> #include <stdio.h>int main() { int x = -5; assert(x >= 0); // program stops here printf("x = %d\n", x); return 0; } |
⚠️ Assertions are removed in production builds using:
gcc -DNDEBUG program.c
5. setjmp() and longjmp() (Manual Exception Handling)
Used to jump to a saved execution point — similar to exceptions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <stdio.h> #include <setjmp.h>jmp_buf buffer; void testError() { printf("Error occurred! Jumping...\n"); longjmp(buffer, 1); } int main() { if (setjmp(buffer) == 0) { printf("Normal execution.\n"); testError(); } else { printf("Recovered from error.\n"); } return 0; } |
🧪 Real Example: Safe File Opening
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include <stdio.h> #include <errno.h> #include <string.h>int main() { FILE *file = fopen("input.txt", "r"); if (file == NULL) { perror("Failed to open file"); return 1; // handle error } printf("File opened successfully.\n"); fclose(file); return 0; } |
🧠 Best Practices
✔ Always check return values (especially for I/O and pointer operations)
✔ Use errno, perror(), and strerror() for readable errors
✔ Use assert() in debugging, not production
✔ Use setjmp() and longjmp() only for advanced cases
🏁 Summary Table
| Technique | Best For |
|---|---|
| Return codes | Simple functions |
errno | System/library errors |
perror() / strerror() | User-friendly error messages |
assert() | Debug/testing |
setjmp() / longjmp() | Advanced error control |
