Error Handling in C Programming
Error handling in C is an essential aspect of writing reliable and maintainable code. Since C does not provide built-in exception handling like some higher-level languages, programmers must implement their own error-handling logic using standard tools such as return codes, errno
, and assertions.
1. General Approach to Error Handling
In C, most functions signal errors through:
- Return values (e.g.,
NULL
or-1
) - Setting global variables like
errno
- Manual checks with conditional statements
Always check the return value of library functions (e.g., memory allocation, file handling, system calls) to ensure that operations have completed successfully.
2. Using errno
for Error Reporting
The C standard library defines errno
in <errno.h>
, a global integer variable that is set by system calls and some library functions to indicate what error occurred.
Key Points:
errno
is not automatically reset to 0, so set it to 0 before calling a function if you want to check whether an error occurred.- After a failure,
errno
contains an error code (e.g.,ENOMEM
,EINVAL
,EIO
). - You can use
perror()
orstrerror()
to print or interpret the value oferrno
.
Useful Functions:
Function | Description |
---|---|
perror() |
Prints a human-readable error message to stderr |
strerror() |
Returns a string describing the error code |
Common errno
Values:
Macro | Meaning |
---|---|
ENOMEM |
Not enough memory |
EINVAL |
Invalid argument |
EIO |
I/O error |
EPERM |
Operation not permitted |
ENOENT |
No such file or directory |
Best Practices with errno
:
- Include
#include <errno.h>
at the top of your program. - Set
errno = 0
before making a call. - After the call, check if it failed (e.g., returned
NULL
) and inspecterrno
. - Print the error message using
perror()
orstrerror(errno)
.
3. Using assert
for Debugging
The assert
macro is defined in <assert.h>
and is used to perform sanity checks during development. It evaluates a condition, and if the condition is false, the program prints an error message and terminates.
Syntax:
assert(expression);
- If
expression
evaluates to false, the program terminates and displays the line number and file where the failure occurred. - Assertions are generally used to validate assumptions during development and testing.
- They can be disabled in release builds by defining
NDEBUG
before including<assert.h>
.
Best Use Cases for assert
:
- Checking for null pointers.
- Validating preconditions and postconditions.
- Ensuring array indices are within bounds.
- Detecting logic errors during development.
4. Return Code Convention
C programs often follow these return conventions:
0
for success- Non-zero for failure
This convention is followed in main()
and other functions, helping external tools (shell scripts, compilers, etc.) detect whether a program executed successfully.
5. Summary Table
Tool | Purpose | Best Used When |
---|---|---|
errno |
Identify error from standard/library/system calls | When function may fail silently |
perror() |
Print error message | When you want detailed error output |
strerror() |
Convert error code to message | When you want to display/log messages |
assert() |
Terminate on logic failure | For debugging and catching logic errors |
Error handling in C may be manual, but it is powerful when done correctly. Proper use of errno
and return values helps you write robust and predictable programs. assert
helps catch mistakes early during development. By combining careful return value checking, diagnostic tools like errno
, and assertions, we can ensure that your C programs behave reliably, even under unexpected circumstances.