strerror
tags: errno.h, strerror, string.h
The strerror
function maps an error number into a string description of that
error.
char *
strerror(int errnum);
It returns a pointer to the string representation of the error, the contents of which are implementation-defined.
Local Variables
We'll use a local variable to point to the string description corresponding to the received error number. This let's us modify what string is pointed to and have a single return statement (as we'll see shortly).
char *str = NULL;
Error Checking
No error checking is necessary for this function, or more accurately, the error checking will be handling by a switch statement that maps the error number to a string description.
Implementation
The total number of error numbers supported by the implementation is only two at
this point (EDOM
and ERANGE
from errno.h
), however it's is expected to
grow in the future. This presents a good use case for a switch
which makes for
a cleaner implementation over the use of a large chain of if
/else if
/else
statements. As more error numbers are defined in the future, new cases will be
added to translate them.
If the error number is unknown we'll still translate this into a message indicating as such. This way our implementation always returns a description. After the switch, return the pointer to the string that was chosen.
switch (errnum)
{
case EDOM:
str = "EDOM - An input argument is outside the domain over which the mathematical function is defined";
break;
case ERANGE:
str = "ERANGE - The result of the function cannot be represented as a double value";
break;
default:
str = "E??? - Unknown error number";
break;
}
return str;
It's worth mentioning a short side note on style here. When possible, welibc chooses to limit the width of code to 80 characters which aids in readability. The C language supports splitting these long descriptions across multiple lines which might look like the following:
switch (errnum)
{
case EDOM:
str = "EDOM - An input argument is outside the domain over which the " \
"mathematical function is defined";
break;
/* ... */
Although this maintains the 80-character width, it presents a problem when
searching through the source code with a tool like grep
.
If you were interested in where this error message came from then you might grep
for the string "outside the domain"
which would get you to the right place.
However, if you chose to search for "the mathematical function"
then your
search wouldn't return any results because that string wouldn't exist on a
single line within the welibc code base. For that reason, I consider it to be
worth breaking the 80-character width to ensure easy searching later on.
Testing
Since the strings returned by strerror
are implementation-defined, we can't
test the contents of the strings themselves - we can only test that a string was
returned. This simplifies the tests as we only need to check that the returned
pointer is not a null pointer. We'll test the currently supported errno
values
in addition to the unsupported error number 0
.
int
strerrorTest(void)
{
int errnums[] = { 0, EDOM, ERANGE };
size_t i = 0;
int ret = 0;
for (i = 0; i < sizeof(errnums)/sizeof(errnums[0]); i++)
{
if (!strerror(errnums[i]))
{
ret = 1;
break;
}
}
return ret;
}
Conclusion
Unfortunately, strerror
is a somewhat boring library function. The
implementation chooses how to represents each error number as a string and
returns those representations as appropriate.
char *
strerror(int errnum)
{
char *str = NULL;
switch (errnum)
{
case EDOM:
str = "EDOM - An input argument is outside the domain over which the mathematical function is defined";
break;
case ERANGE:
str = "ERANGE - The result of the function cannot be represented as a double value";
break;
default:
str = "E??? - Unknown error number";
break;
}
return str;
}