a C-programm can fail to execute under special circumstances in Linux. Example: You allocate some space and the OS denies it.
char *buffer = (char *) malloc(1024);
if (buffer == NULL)
return ENOMEM;
This failure is marked by the return code which is delivered to the OS.
So my question is, what is the convention, when a program detects an error. Should it return a positive or a negative return code ?
My professor told me in UNIX/Linux allways to return a negative error code. But the errno-Codes are all positive integers. Also the define-Statement of EXIT_FAILURE in is 1, a positive integer. So should my code look like this:
char *buffer = (char *) malloc(1024);
if (buffer == NULL)
return -ENOMEM;
or like the code above? I know from Linux-Kernel-Modules that in most cases they return a negative error code on failure.
Thanks for helping.
So my question is, what is the convention, when a program detects an error. Should it return a positive or a negative return code ?
You do not have the luxury (or responsibility) of making that choice. From the point of view of C in general, your choices fall into three categories:
The exit status you specify is either 0
or EXIT_SUCCESS
(which are not necessarily distinct). This indicates successful completion.
The exit status you specify is EXIT_FAILURE
. This indicates unsuccessful completion.
The exit status you specify is anything else.
The result signaled to the host environment is implementation-defined in every case, though in the first it is one that communicates success, and in the second it is one that communicates failure.
Now, on Linux and other operating systems implementing POSIX exit()
semantics, the implementation-definedness is standardized:
The value of status may be
0
,EXIT_SUCCESS
,EXIT_FAILURE
, or any other value, though only the least significant 8 bits (that is,status & 0377
) shall be available fromwait()
andwaitpid()
;
(IEEE Std 1003.1-2008, 2016 Edition; emphasis added). Those are the traditional UNIX semantics; only the least-significant 8 bits of the exit status you specify matter, so the signedness is lost. However, the current version of POSIX goes on to say:
the full value shall be available from
waitid()
and in thesiginfo_t
passed to a signal handler forSIGCHLD
.
Thus, you can communicate a negative number to the parent process if it knows to look for one. In general, however, it won't do. In particular, if the parent process is the shell then it won't do.
My professor told me in UNIX/Linux allways to return a negative error code.
That sounds more like an instruction about function return codes for functions other than main()
, but I don't see why you think our second guessing about what your professor meant would be more reliable than asking your professor for clarification directly.
But the errno-Codes are all positive integers.
Well, another thing to clarify with your professor would be whether he was giving you specific instructions about how he expects you to write functions for his class (more likely), or whether he was making an assertion about general C or POSIX convention (unlikely, because there are many POSIX functions of which it is not true), or something else.
Note well that C standard library functions do not return errno
codes. When they return a code indicating failure (often, but not always, a negative number), the programmer is obliged to consult the errno
variable for a detailed reason -- the function return code generally does not carry that information. Some functions standardized by POSIX but not C do return errno
codes directly; obviously, these do not follow your professor's prescription.
Note also that errno
values are for communicating between functions called by the same program, not for communicating with the program's environment. They are not intended for use as program exit statuses, and in particular, there is no guarantee that their values fit in eight bits (see above).
Also the define-Statement of EXIT_FAILURE in is 1, a positive integer. So should my code look like this:
The value of EXIT_FAILURE
is implementation-dependent. You can therefore glean only implementation-specific insight from it. As you can see, however, the general-purpose exit status indicating program failure in your implementation is 1
.
On Linux and other POSIX(-ish) systems, you achieve best integration with the shell by choosing failure statuses between 1 and 125, as the shell designates special significance to statuses 126-255, and, of course, interprets status 0 as success.
char *buffer = (char *) malloc(1024); if (buffer == NULL) return -ENOMEM;
or like the code above? I know from Linux-Kernel-Modules that in most cases they return a negative error code on failure.
Again, no. Errno codes are not meant for use as program exit codes, and only in rather special circumstances should you try to exit with a negative status. A common convention is to write an informative error message to stderr
(perror()
serves exactly this purpose) and then exit with status 1 or (better, IMO) EXIT_FAILURE
.
If you want to provide exit codes that describe the nature of the failure then it is up to you to define their values and significance on a per-program basis, remembering that for best compatibility you have only 1 - 125 to work with.