C Programming language itself doesn't provide any good mechanism for error
handling. But standard library and Unix/Linux system calls do provide a
convinient way to handle errors. External variable errno, function strerror and
function perror from library <errno.h>, <string.h> and <stdio.h> are all the
things you need to make your programs more robust.
The general way to use errno to handle error is like this:
if you want to print error messages onto standard output(screen), you can use
perror as an alternative.
perror( const char *msg );
perror( msg ); is equal to printf( "%s: %s/n", msg, strerror( errno ) );
There is a little difference between perror and strerror, the former is more
elegant and easier to use, but it can print messages on standard output only and
its format is predefined which cannot be changed. strerror provides much more
freedom. You can write the message to anywhere and use any format you want.
We know something goes wrong according to the return value of some functions
like fopen etc. Then we can retrieve the detail information of the error through
errno and strerror and output the info to user or do some recovery operations.
But many times, we cannot know abnormal things happened through return value.
fgets, for instance, would return NULL if either EOF reached or error occured.
For these situations, we need to check errno to see whehter error has occured.
Before you do that you have to know two rules about errno: First, its value
is never cleared by a routine if an error does not occur. Therefore, we should
examine its value only when the return value from a function indicates that an
error occurred. Second, the value of errno is never set to 0 by any of the
functions, and none of the constants defined in <errno.h> has a value of 0.
As a result, if you want to know whether there is an error through errno, you'd
better initialize it, then see if it remains its initial value. Like this:
In addition, if you write some error handling routines for system calls, you'd
better save the original errno. Because, an error could occur during your
handling routine and errno could be overwritten. Take err_doit in comhdr.h for
example:
Here, vsprintf might fail and modify errno, if so, the following strerror(errno)
will no longer be the original error. Therefore, we have to save a copy of errno
in errno_save, just in case.