Error Handling and Debugging in C
Error handling is a critical aspect of any robust C program. C provides several mechanisms for error handling and debugging, including return codes, errno
, perror()
, strerror()
, and debugging tools like GDB.
1. Error Codes and Return Values
In C, functions typically indicate success or failure through return values. A function may return 0
for success and a non-zero value (often -1
) for failure. These return values can be checked to handle errors gracefully.
Example: Checking Return Values
#include <stdio.h>
int divide(int a, int b) {
if (b == 0) {
return -1; // Error: Division by zero
}
return a / b;
}
int main() {
int result = divide(10, 0);
if (result == -1) {
printf("Error: Division by zero\n");
} else {
printf("Result: %d\n", result);
}
return 0;
}
Explanation:
- The
divide()
function returns-1
if the denominator is zero, signaling an error. - The error is handled by checking the return value in the
main()
function.
Output:
Error: Division by zero
2. errno, perror(), and strerror()
In addition to return values, C provides the errno
variable, which stores error codes set by system calls and library functions when an error occurs. The perror()
and strerror()
functions are used to display human-readable error messages.
Using errno
errno
is a global variable that stores the error code when a function encounters an error.
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
FILE *file = fopen("non_existent_file.txt", "r");
if (file == NULL) {
// Print the error code and message
printf("Error code: %d\n", errno);
printf("Error message: %s\n", strerror(errno));
}
return 0;
}
Explanation:
fopen()
fails because the file does not exist, settingerrno
to the corresponding error code.strerror(errno)
returns a human-readable string describing the error.
Output:
Error code: 2
Error message: No such file or directory
Using perror()
perror()
is a simpler way to print an error message directly based on errno
.
#include <stdio.h>
int main() {
FILE *file = fopen("non_existent_file.txt", "r");
if (file == NULL) {
// Print the error message using perror
perror("File error");
}
return 0;
}
Explanation:
perror()
automatically prints an error message corresponding to the current value oferrno
.
Output:
File error: No such file or directory
3. Debugging with GDB
GDB (GNU Debugger) is a powerful tool for debugging C programs. It allows you to step through your code, inspect variables, set breakpoints, and more.
Basic GDB Commands
-
Compile with debugging symbols: Add the
-g
flag when compiling.gcc -g program.c -o program
-
Start GDB: Run GDB on your executable.
gdb ./program
-
Set a breakpoint: Pause execution at a specific line.
(gdb) break main
-
Run the program:
(gdb) run
-
Step through the code: Use
next
to execute the next line of code.(gdb) next
-
Inspect variables: Print the value of variables.
(gdb) print var_name
-
Continue execution: Resume program execution.
(gdb) continue
-
Quit GDB:
(gdb) quit
Example: Using GDB to Debug a Segmentation Fault
Consider the following buggy code:
#include <stdio.h>
int main() {
int *ptr = NULL;
*ptr = 10; // Dereferencing a null pointer (causes segmentation fault)
return 0;
}
Debugging Steps:
-
Compile the code with debugging symbols:
gcc -g segfault.c -o segfault
-
Run the program with GDB:
gdb ./segfault
-
Set a breakpoint at
main()
:(gdb) break main
-
Run the program:
(gdb) run
-
Step through the code using
next
and identify the line causing the segmentation fault. -
Inspect the value of
ptr
to see that it isNULL
.
GDB Output Example:
Program received signal SIGSEGV, Segmentation fault.
0x00000000004004c7 in main () at segfault.c:6
6 *ptr = 10;
(gdb) print ptr
$1 = (int *) 0x0
Explanation:
- GDB shows that the segmentation fault occurred at line 6 (
*ptr = 10
). - Inspecting
ptr
withprint ptr
reveals thatptr
isNULL
, which causes the crash.
4. Diagram for Error Handling and Debugging
5. Recap
- Error Codes and Return Values: Functions indicate success or failure with return values.
- errno: Stores error codes set by functions when errors occur.
- perror() and strerror(): Functions for printing human-readable error messages.
- GDB: A powerful tool for debugging C programs.
These tools and techniques provide a structured way to handle errors and debug issues in C programs, ensuring better code reliability and maintainability.