1

I've seen some previous posts on return 1 and return 0, and here is what I understand:

For the user (someone who won't look at the source code) of the program, there is no distinction between return 1 and return 0.

For the programmer, return 1 implies error, and return 0 implies normal execution.

Am I understanding this correctly?

Hi, sorry, I didn't think this mattered, but I am talking about in the context of main().

roulette01
  • 1,984
  • 2
  • 13
  • 26
  • 3
    1. this can vary wildly, 2. the user generally won't ever see a return value directly unless logged or reported. – crashmstr Mar 18 '16 at 17:55
  • It's just a convention. `0` might mean OK, `-1` might mean `could not open file`, `-2...` To quote Stroustrup, who quoted Humpty Dumpty: _“When I use a word, it means just what I choose it to mean — neither more nor less.”_ – zdf Mar 18 '16 at 18:16
  • Reopened because the linked question purported to answer a dozen different questions, none of which was this one. – Pete Becker Mar 18 '16 at 19:11
  • 1
    Are you talking about [program exit status](https://en.wikipedia.org/wiki/Exit_status) returned by `main()` function, or function return values in general? – hyde Mar 18 '16 at 19:15
  • 3
    Please update your question to specify which function you're returning from. If it's `main`, the language standard has a few things to say about it. If you're talking about some other function, it depends entirely on how *that function* is supposed to behave. – Keith Thompson Mar 18 '16 at 19:25

3 Answers3

2

The exit status of a program can be whatever a given program wants it to be [mean].

While most programs get by with: 0=success, 1=error, some others do different things.

Some examples from POSIX/Unix/Linux:

The true program always exits with 0. The false program always exits with 1. So, [academically speaking] did false fail?

The cmp and diff programs do: 0=files match, 1=files differ, 2=other [2 usually means one of the files being compared does not exist].

The rsync program has many exit codes: 0=success, non-zero=error. But, there are many ways rsync can fail. Because rsync works on a live FS, some errors can be retried. For example, a file on the source is removed while the rsync is happening (code 23 or 24). This can be retried. Likewise for some timeout errors.

EXIT VALUES
0      Success

1      Syntax or usage error

2      Protocol incompatibility

3      Errors selecting input/output files, dirs

4      Requested action not supported: an attempt was made  to  manipu‐
       late  64-bit files on a platform that cannot support them; or an
       option was specified that is supported by the client and not  by
       the server.

5      Error starting client-server protocol

6      Daemon unable to append to log-file

10     Error in socket I/O

11     Error in file I/O

12     Error in rsync protocol data stream

13     Errors with program diagnostics

14     Error in IPC code

20     Received SIGUSR1 or SIGINT

21     Some error returned by waitpid()

22     Error allocating core memory buffers

23     Partial transfer due to error

24     Partial transfer due to vanished source files

25     The --max-delete limit stopped deletions

30     Timeout in data send/receive

35     Timeout waiting for daemon connection
hyde
  • 60,639
  • 21
  • 115
  • 176
Craig Estey
  • 30,627
  • 4
  • 24
  • 48
  • @hyde The 1st sentence is universally true [and, ironically, opens pandora's box to include WinX]. WinX tends to abuse things with diff codes for diff apps. Long ago, I got tired of having to mention WinX as the exception [to _everything_ standard]. It's dying a slow death, so I just ignore it. Error codes mean less there as its mostly monolithic launch of mammoth app. One exception is using power shell. With WinX, "fork" an app and now you have a matrix of apps vs codes to deal with. OP's question tended to frame this to POSIX systems, so let's restrict to that. Otherwise answer is 5x longer – Craig Estey Mar 18 '16 at 21:42
  • Taking the 1st sentence, I assume you mean exit status can *mean* (instead of "can be", because for example on Linux, exit code can't be 0x80000000) whatever a program wants, including nothing at all. Well, it's not uncommon that program *can't* have whatever exit code it wants, because it needs to interface with outside world, which will abort with error if program has 1 mean success (of course then you add a wrapper/adapter of some kind, but from outside world point of view, the wrapper is the program). – hyde Mar 19 '16 at 07:12
  • @hyde It's the other way round. It's an _exit_ code, not an _error_ code. While 0/1 is the norm, it is _not_ an absolute. If pgm X invokes pgm Y, X _must_ honor whatever exit codes Y uses [from Y's documentation--for POSIX, within 0-255], or X can't invoke Y. I have some pgms that return descriptive codes [128+]. (e.g.) For a server, I have a "guard" pgm X that (re)invokes Y [which may abort on an edge case--and has a bug]. X must keep Y up. It decides this based on what Y returned: soft, hard, timeout, crash. An exit code is like a function return. The callee specifies what it means. – Craig Estey Mar 19 '16 at 20:28
  • Which ever was written first, caller or callee, gets to specify the interface it wants. Then which ever is written later must conform to it, one way or another (maybe simply with wrapper like `myprogram || true`). I guess it depends on perspective, which one thinks is more common or important, so we're probably not disagreeing here. – hyde Mar 20 '16 at 07:20
  • @hyde We're _not_ disagreeing, just complementing. Most pgms that [want to] play nice, use 0/1. Some, _must_ do other things. (e.g.) `rsync` uses `ssh` to start the remote server, so it communicates out-of-band data with exit codes. 5/12 is a protocol error. If that happens [and how else would the server convey that?--the protocol can't be used], the client may retry with an older protocol version [which may now work], making it more robust. WinX has codes 0-16,000. They are like errno but any pgm can abort with them if it can't handle one. – Craig Estey Mar 21 '16 at 03:56
1

In some contexts the operating system pays attention to the returned value from a program. For this purpose, the only portable return values are EXIT_SUCCESS, EXIT_FAILURE, and 0, where 0 is equivalent to EXIT_SUCCESS. The values of the named constants come from <cstdlib> or <stdlib.h>.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
0

Assuming you are talking about main() function return value here, which becomes "the program exit status" (wiki link).

For GUI programs, the return value is rarely used for anything, be it programmer or user of the program.

On the other hand, for console programs and command line utilities, the return value is often very useful, sometimes even the whole purpose and only output of the program. Example is Unix test utility. User uses it to test some condition, such as test -f file.txt to test if file.txt exists. It will return exit code 0 (which generally means success) if file exists, non-zero if it does not.

Of course in these cases, user of the program is generally someone for example writing a shell script or command line "one-liner", but still they are users of the program, and won't be looking at the programs source code to use the program.


About C and standards: Note that C standard itself does not say much about what values main can return, other than providing two constants EXIT_SUCCESS (I think this is 0 always, but no standard reference handy) and EXIT_FAILURE (which is then non-zero), and leaving rest for the implementation. But in MSDOS/Windows/Unix/Linux, you can basically provide an exit status at least in range 0-255, depending on OS a possibly much larger range also including negative values, and then use these to mean different things. From OS point of view, having 0 mean success is just a convention or recommendation, not really enforced in any hard way, and there it is up to the parent process to interpret the return value correctly.

hyde
  • 60,639
  • 21
  • 115
  • 176
  • 1
    The actual minimum range is 0-255. The historical reason is that when Unix was first developed for the PDP/11 circa 1970, an `int` was 16 bits [and the 8 bit code still works there]. AFAIK, the only OS that [might] allow a larger value would be WinX [via some API call other than `wait(2)`]. If `int` had always been 32 bits, we'd likely have a 24 bit wide error code [or donate some bits to increase the width of the signo]. But, to maintain _reverse_ compatibility (e.g. pgm built for 32 bit int will work on "retro" 16 bit int machine), most OSes will truncate the code to 8 bits – Craig Estey Mar 18 '16 at 20:38
  • @CraigEstey Yeah. I remembered dos only having 7 bit unsigned range, but at least the Wikipedia page I linked to says it was 0..255 there too. – hyde Mar 18 '16 at 20:46
  • 1
    I used to think it was 127, but I've seen programs that do `exit(-1)` [ugly, IMO] and I would get an exit code of 255. So, I finally looked up the definition of `WEXITSTATUS` in the `.h` file – Craig Estey Mar 18 '16 at 21:09