Return Code on failure. Positive or negative?

前端 未结 6 1063
野的像风
野的像风 2021-01-04 18:14

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         


        
相关标签:
6条回答
  • 2021-01-04 18:33

    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 from wait() and waitpid();

    (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 the siginfo_t passed to a signal handler for SIGCHLD.

    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.

    0 讨论(0)
  • 2021-01-04 18:41

    Typically a Linux program returns 0 on success or non-zero on failure. There are some exceptions (grep for example, which has values to represent whether it found a match). The reason for this is that the bash prompt defines true as 0, and false as 1, so it makes scripting simple:

    somecmd && action "if succesful"
    

    But that's the program itself. For code inside of a program, there is often a mixture of conventions. A common one is to return 0 (or positive) on success, or negative on failure. The reason behind this is that all instruction sets (that I'm aware of), have a branch-if-zero, or branch-if-less-than-zero instructions, which means its only one instruction to do the comparison (as opposed to having to do a compare and then branch if the comparison matched).

    0 讨论(0)
  • 2021-01-04 18:44

    The convention for a not further specified error code from your program is to use EXIT_FAILURE. It will be defined to a value your OS recognizes as a failure exit code.

    The macros defined in errno.h are not meant as return codes for processes but only for errors during program execution. The standard library will put them in the global errno, you could also use them as return codes from functions if you like. Three of them are specified by the C standard: EDOM, EILSEQ and ERANGE. A lot more are specified by POSIX. Do not use these as return codes from main() (or as argument to exit()).

    0 讨论(0)
  • 2021-01-04 18:44

    errno is a global variable you would set with the error number. The convention is to set errno and then return a negative number (usually negative one). The negative return value indicates errno should be checked. Using your example (and putting it into a function), it might look like this:

    int allocate_buffer(char *buffer) {
        buffer = malloc(1024);
        if (buffer == NULL) {
            errno = ENOMEM;
            return -1;
        }
        return 0;
    }
    

    The caller would then know if there was an error based on the return value, and check errno to see what the error was and decide how to proceed from there.

    0 讨论(0)
  • 2021-01-04 18:50

    The exit code on UNIX/Linux from a process, the return statement in main() or a call to exit(), is unsigned in the range 0 - 255.

    From a function it can be any type you want it to be. Many library functions return -1 on error.

    However that is not always possible, particularly functions that normally return a pointer. By convention those functions return NULL on error, examples are fopen() and malloc().

    These return codes only indicate that an error has occurred, not what the error is, usually (on error) the global errno is also set to a positive error code giving further information. See man errno

    0 讨论(0)
  • 2021-01-04 18:55

    5.1.2.2.3 Program termination

    If the return type of the main function is a type compatible with int, a return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument; 11) reaching the } that terminates the main function returns a value of 0. If the return type is not compatible with int, the termination status returned to the host environment is unspecified.

    7.22.4.4 The exit function:

    Finally, control is returned to the host environment. If the value of status is zero or EXIT_SUCCESS, an implementation-defined form of the status successful termination is returned. If the value of status is EXIT_FAILURE, an implementation-defined form of the status unsuccessful termination is returned. Otherwise the status returned is implementation-defined.

    I found this to be self-descriptive.

    0 讨论(0)
提交回复
热议问题