Noeud:Error Handling, Noeud « Next »:Pattern Matching, Noeud « Previous »:Input and Output, Noeud « Up »:The GNU C Library
UNIX programs always return an exit code. Exit codes usually go unnoticed, but are always present. They are most often used by shell scripts and by make, which may take some alternative action if the program doesn't finish correctly.
By convention, most programs return an exit code of zero to indicate normal completion. Nonzero exit codes usually mean that an error has occurred. There are some notable violations of this convention (e.g., cmp and diff), but we recommend you obey it. C shell users can print exit codes by entering the command:
% echo $status
If you use the Bourne shell (sh) or a derivative like bash, you can print the exit code with the command:
$ echo $?
When you are writing a program, to have it return an error code, call the function exit, with the error code as an argument:
int code; exit (code);
Although the error code is an int, its value should be between 0 and 255.
Functions aren't that different from programs: their returned value
indicates whether they succeeded or failed. If you want to write healthy
code, you should always check the value returned from a function. The
code below shows one way to test for an error:
#include <stdio.h> /* write to standard output and check for error */ if (printf (...) == EOF) exit (1); /* output failed; terminate */ /* normal processing continues */ ...
The manual page for printf says that it returns the constant EOF
if it fails; if it succeeds, it returns the number of bytes transmitted.
If you look in stdio.h
, you'll see that EOF
is defined as
-1. As a rule, a positive or zero return value indicates success; a
negative value indicates failure. However, there are many exceptions to
this convention. Check the manual page, and if a symbolic constant
(like EOF
) is available, use that rather than a hard-wired
constant.
If you want more information about what went wrong with your function,
you can inspect the errno variable. When a system call fails, it stores
an error code in errno. UNIX then terminates the system call,
returning a value that indicates something has gone wrong - as we just
discussed. Your program can access the error code in errno
,
figure out what went wrong, and (possibly) recover, as in the example
below:
#include <stdio.h> #include <errno.h> FILE *fd; int fopen_errno; main (int argc, char **argv) { /* try opening the file passed by the user as an argument */ if ((fd=fopen (argv[1], "r")) == NULL) { /* test errno, and see if we can recover */ fopen_errno = errno; /* save errno */ if (fopen_errno == ENOENT) /*no such file or directory*/ { /* get a filename from the user and try opening again */ ... } /* otherwise, it's an unknown error */ else { perror ("Invalid input file"); exit (1); } } /* normal processing continues */ }
Example 2.15: Use of errno
On UNIX systems, the header file errno.h
defines all
possible system error values. Note that this code immediately copies
errno to a local variable. This is a good idea, since errno
is
reset whenever a system call from your process fails, and there's no way
to recover its previous value.
Another way to use the error number, without examining it yourself, is
to call perror
, which sends a message describing the error to the
standard error I/O stream. It's used like this:
#include <stdio.h> perror ("prefix to message");
The prefix to message
given as an argument to perror
is
printed first; then a colon; then the standardized message. For
example, if the previous function call failed with the errno
ENAMETOOLONG
because the user passed a long string of garbage as
an argument, the function call perror ("Invalid input file");
would result in the output:
Invalid input file: File name too long
void error (int status, int errnum, const char *format, ...) | glibc function |
void error_at_line (int status, int errnum, const char *filename, unsigned int lineno, const char *format, ...) | glibc function |