Error handling in C is performed using function return values, error codes, and the global errno variable, since C does not provide built-in exception handling like try-catch.
- Most functions return -1, NULL, or set errno when an error occurs.
- if statements are commonly used to detect and handle these errors.
errno
errno is a global variable defined in the <errno.h> header file that stores the error code when a library function fails. It helps identify the reason for the error during program execution.
- Automatically set to a specific error code when a function encounters an error.
- Used with functions like perror() and strerror() for error handling.
#include <stdio.h>
#include <errno.h>
int main() {
FILE *fp = fopen("missing.txt", "r");
if (fp == NULL) {
printf("Error Code: %d\n", errno);
perror("Error");
}
return 0;
}
Output
Error Code: 2
Below is a list of a few different errno values and their corresponding meaning:
| errno value | Error |
|---|---|
1 | Operation not permitted |
2 | No such file or directory |
3 | No such process |
4 | Interrupted system call |
5 | I/O error |
6 | No such device or address |
7 | The argument list is too long |
8 | Exec format error |
9 | Bad file number |
10 | No child processes |
11 | Try again |
12 | Out of memory |
13 | Permission denied |
Different Methods for Error Handling
Different methods are used to handle different kinds of errors in C. Some of the commonly used methods are:
1. Using if-else
In C, if-else statements are commonly used for error handling because the language does not provide built-in exception handling like try-catch. They allow programs to detect and handle errors during execution.
- Checks the return value of functions to detect errors.
- Executes appropriate error-handling code when an error occurs.
#include <errno.h>
#include <stdio.h>
int main() {
FILE* fp;
// opening a file which does not exist
fp = fopen("gfg.txt", "r");
if(fp == NULL){
printf("File opening error");
}else{
printf("File open successfully");
}
return 0;
}
Output
File opening error
Syntax
if (condition) {
// Error handling code
} else {
// Normal execution
}
2. perror()
The perror()function is used to print a descriptive error message to the standard error stream (stderr). It displays the error message corresponding to the current value of the global errno variable.
- Prints a user-defined message followed by the system error description.
- Commonly used after a function fails to identify the cause of the error.
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main(){
FILE* fp;
// Try opening a non-existent file, which sets errno
fp = fopen("gfg.txt", "r");
// Print the errno value after failed file opening
printf("Value of errno: %d\n", errno);
perror("Message from perror");
return 0;
}
Output
Value of errno: 2
Syntax
void perror(const char *message);
3. strerror()
The strerror() function is also used to show the error description. This function returns a pointer to the textual representation of the current errno value.
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main() {
FILE* fp;
// Try opening a non-existent file, setting errno
fp = fopen("gfg.txt", "r");
// Print errno value and corresponding error message
printf("Value of errno: %d\n", errno);
printf("The error message is : %s", strerror(errno));
return 0;
}
Output
Value of errno: 2 The error message is : No such file or directory
4. ferror()
The ferror() function is used to check if an error occurred during a file operation. It returns a non-zero value if there was an error during the file operation.
#include <stdio.h>
int main() {
FILE *fptr = fopen("gfg.txt", "w");
// Write data to the file
fprintf(fptr, "Hello, GFG!");
// Check error after writing data into file
if(ferror(fptr)==0)
printf("Data written successfully.");
fclose(fptr);
return 0;
}
Output
Data written successfully.
5. feof()
The feof() function checks whether the end of a file has been reached during reading operations. It helps to identify when there is no more data to read from the file.
#include <stdio.h>
int main () {
FILE *fp = fopen("gfg.txt","r");
if (fp == NULL)
return 0;
do {
// Taking input single character at a time
char c = fgetc(fp);
// Checking for end of file
if (feof(fp))
break ;
printf("%c", c);
}while(1);
fclose(fp);
return(0);
}
gfg.text
Welcome to GeeksforGeeks
Output
Welcome to GeeksforGeeks
clearerr()
The clearerr() function is used to clear the error and EOF flags for a stream. It allows recovery from errors and allows the stream to be reused for further operations.
#include <stdio.h>
int main() {
FILE *fptr = fopen("gfg.txt", "w+");
fprintf(fptr, "GeeksForGeeks!");
while (fgetc(fptr) != EOF);
if(feof(fptr)){
printf("EOF encounter \n");
}
// Reset EOF using clearerr
clearerr(fptr);
if(!feof(fptr)){
printf("Reset the EOF successfully");
}
fclose(fptr);
return 0;
}
Output
EOF encounter Reset the EOF successfully
Exit Status
Exit Status indicates whether a C program terminated successfully or unsuccessfully. The exit() function returns a status code to the operating system using the constants EXIT_SUCCESS and EXIT_FAILURE defined in <stdlib.h>.
- EXIT_SUCCESS indicates that the program executed successfully.
- EXIT_FAILURE indicates that the program terminated due to an error.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
FILE* fp;
// Attempt to open a non-existent file in binary mode
fp = fopen("gfg.txt", "rb");
if (fp == NULL) {
printf("Value of errno: %d\n", errno);
printf("Error opening the file: %s\n", strerror(errno));
perror("Error printed by perror");
// Exit the program with failure status
exit(EXIT_FAILURE);
// This line will not be printed because of exit()
printf("I will not be printed\n");
}
// If the file is opened successfully
else {
fclose(fp);
exit(EXIT_SUCCESS);
printf("I will not be printed\n");
}
return 0;
}
Output
Value of errno: 2
Error opening the file: No such file or directory
Error printed by perror: No such file or directory
Error Handling without Predefined Methods
Some errors in C can be handled without using predefined error-handling functions by validating conditions before executing operations. This helps prevent program crashes and undefined behavior.
- Checks conditions such as division by zero, invalid input, or array bounds before execution.
- Prevents runtime errors by handling exceptional cases manually.
#include <stdio.h>
int main() {
int num1 = 10, num2 = 0;
if (num2 == 0)
printf("Error: Division by zero is not allowed\n");
else
printf("Result: %d", num1 / num2);
return 0;
}
Output
Error: Division by zero is not allowed