4

I was trying to think of a quick and illustrative way to generate a non-successful exit status and thought dividing by zero with the bc would be a good idea.

I was suprised to discover that although it does generate a runtime error, the exit status is still 0:

$ echo 41 + 1 | bc 42 $ echo $? 0 $ echo 42/0 | bc Runtime error (func=(main), adr=6): Divide by zero $ echo $? 0 
  • Why does the bc utility not fail with a non-zero exit status?

Note: For a quick non-zero exit status I'm using return 1

Also, from shell-tips:

$ expr 1 / 0 expr: division by zero $ echo $? 2 
2
  • I would use ls nosuchfile for the illustration, by the way. Or if I want to show how non-zero exit statuses do have conventional meanings, I would set up as follows: echo hello > file1; echo hello > file2; echo goodbye > file3 and then show the exit status for cmp file1 file2, cmp file1 file3, cmp file1 file4. Commented Apr 4, 2017 at 0:22
  • You cannot devide by 0? The answer is unlimited? Commented Apr 4, 2017 at 0:23

2 Answers 2

7

bc implementations differ a bit in their return status, but the general idea is that if you supply valid input then bc exits with the status 0. 42/0 is valid input: there's no read error, and it's even a syntactically valid expression, so bc returns 0. If you passed a second line with another operation, bc would perform it. This is different from expr whose purpose is to evaluate a single arithmetic expression; here the outcome of that single expression determines the return status.

The most straightforward way to generate an exit status that indicates failure is to call false. Things like expr 1 / 0 only have their place in obfuscated programming contests.

6

Look in the spec; this is expected behavior.

All of the input was read correctly by bc, so it produced exit status 0.

If you run bc on a non-existent file, like bc nosuchfile, you will get some other exit status.


For illustrating a non-zero exit status, I would either compare ls somefile and ls nosuchfile, or I would show how exit statuses 1 and 2 are conventionally used (1 for expected error or failure status, 2 for unexpected error) like so:

$ echo hello > file1 $ echo hello > file2 $ echo goodbye > file3 $ cmp -s file1 file2 $ echo $? 0 $ cmp -s file1 file3 $ echo $? 1 $ cmp -s file1 file4 $ echo $? 2 $ 
4
  • Also note: pubs.opengroup.org/onlinepubs/9699919799/utilities/… Commented Apr 4, 2017 at 1:12
  • 1
    @user367890, yes, thanks. I considered adding that to the answer but decided against it, since ultimately it just says, "The reasons are historical." But I will comment that POSIX formalizes what is already standard in practice: requiring behavior different from that of all existing implementations isn't the goal, even if it that behavior might seem like a better design. So "historical reasons" actually describes much of POSIX. Commented Apr 4, 2017 at 1:18
  • 2
    It is accepted behaviour, but not mandated nor recommended (so I wouldn't put expected here). The exit status is unspecified if there's an error. Here, regardless of POSIX conformance, in the case of GNU bc, I'd argue it's a bug as upon that division by zero (but also upon syntax error), it's a fatal error, bc doesn't process further input. Commented Apr 5, 2017 at 8:24
  • @Wildcard: Yes, but a non zero exit code does not indicate there was a failure reading – it could, but an implementation could also exit with <> 0 on for example n / 0. As the Q is “Why does bc exit 0 when dividing by 0?” – one should likely point out that this is an invalid statement. From how I read it, even failure to read input file could also result in exit code 0 as it is unspecified. Perhaps I am wrong. Commented Apr 5, 2017 at 22:22

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.