The perror and strerror Functions in C
- The
perrorfunction prints an error message to standard error (stderr) based on the current value oferrno, providing a textual description of the error. - The
strerrorfunction returns a descriptive string of the error associated with a specific value oferrno, allowing you to obtain the description without printing it immediately. - Both functions are useful for improving error handling in programs written in C language, making error messages more understandable for users.
perroris particularly useful for printing error messages directly when an error occurs, whilestrerroris useful when you want to manipulate or store the error description.
The perror Function
In the previous lesson we saw how some functions of the C standard library use the global variable errno to signal errors. In case of abnormal functioning, these functions set errno to a specific value that indicates the type of error that occurred.
When this happens, it is often useful to provide the user with a more descriptive error message that explains the nature of the error in an understandable way. For this purpose, the C language provides the perror function which stands, precisely, for "print error".
This function is defined in the <stdio.h> header and has the following signature:
void perror(const char *s);
When invoked, the perror function performs 5 operations:
- Checks the current value of
errno. - Retrieves the textual description associated with that value of
errno. - Prints the string passed as argument
s, followed by a colon and a space (": "). - Prints the textual description of the error.
- Terminates the print with a newline character.
To understand how it works, let's revisit the example of calculating the square root of a real number through the sqrt function of the mathematical library <math.h>. This function sets errno to EDOM (domain error) if it is called with a negative argument.
We can use perror to print a clearer error message when this problem occurs:
#include <stdio.h>
#include <math.h>
#include <errno.h>
int main() {
double number;
printf("Enter a real number: ");
scanf("%lf", &number);
errno = 0; // Reset errno before the call
double result = sqrt(number);
if (errno != 0) {
perror("Error in square root calculation");
} else {
printf("The square root of %.2f is %.2f\n", number, result);
}
return 0;
}
Trying to compile and execute the code above, if we enter a negative number, we will get an output similar to the following:
Enter a real number: -9
Error in square root calculation: Numerical argument out of domain
Furthermore, the perror function prints the error message directly to standard error (stderr), which is useful for separating error messages from the normal program output.
The error message printed by perror depends on the value of errno and the local system configuration, so it may vary slightly between different platforms or environments.
In the case of an EDOM error, the default message is "Numerical argument out of domain", but other errors will have different messages.
The strerror Function
Sometimes, it might be necessary to obtain the textual description of an error without printing it immediately. In these cases, we can use the strerror function, defined in the <string.h> header, which returns a descriptive string of the error associated with a specific value of errno.
The signature of the strerror function is the following:
char *strerror(int errnum);
To the strerror function must be passed an integer errnum, which represents the value of errno for which you want to obtain the textual description. The function returns a pointer to a string that contains the error description.
This function is closely related to perror, as perror uses strerror internally to obtain the error description to print.
Furthermore, it is not necessary that errnum be necessarily the current value of errno; we can pass any valid error value to obtain its description.
For example, we can create a program that uses strerror to obtain and print the description of a specific error:
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main() {
int error;
printf("Enter an error number (for example, %d for EDOM): ", EDOM);
scanf("%d", &error);
char *description = strerror(error);
printf("Description of error %d: %s\n", error, description);
return 0;
}
Compiling and executing the program above, if we enter 33 (which corresponds to EDOM on many systems, for example on Linux), we will get an output similar to the following:
Enter an error number (for example, 33 for EDOM): 33
Description of error 33: Numerical argument out of domain
In this way, strerror allows us to obtain the textual description of a specific error without necessarily having to immediately print the error message.