From owner-freebsd-questions@FreeBSD.ORG Tue May 19 18:02:46 2015 Return-Path: Delivered-To: freebsd-questions@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 09A78431 for ; Tue, 19 May 2015 18:02:46 +0000 (UTC) Received: from sola.nimnet.asn.au (paqi.nimnet.asn.au [115.70.110.159]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 591801FB2 for ; Tue, 19 May 2015 18:02:44 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by sola.nimnet.asn.au (8.14.2/8.14.2) with ESMTP id t4JI2S17023820; Wed, 20 May 2015 04:02:28 +1000 (EST) (envelope-from smithi@nimnet.asn.au) Date: Wed, 20 May 2015 04:02:28 +1000 (EST) From: Ian Smith To: Polytropon cc: freebsd-questions@freebsd.org, andrew clarke , Trev Roydhouse Subject: Re: Strange return codes from old but good C program In-Reply-To: Message-ID: <20150520032402.F69409@sola.nimnet.asn.au> References: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 May 2015 18:02:46 -0000 In freebsd-questions Digest, Vol 572, Issue 1, Message: 22 On Mon, 18 May 2015 13:55:07 +0200 Polytropon wrote: > On Sun, 17 May 2015 19:45:09 +0000 (UTC), Will Parsons wrote: > > I don't have the actual C standard, but Harbison & Steele's "C - A > > Reference Manual" (which I think can be relied on) states "If the end > > of the body of *main* is reached without returning, it is treated as > > if *return 0;* were executed". > > In that case, no random return codes should appear. It also > doesn't meet the little test I've wrote (which again matches > with the initially described problem). Quite closely I think, exiting after an executed for loop. > I have written (haha) the following "test case": > > % cat returntest.c > main() { > int i, j; > for(i = 0, j = 0; i < 100; i++) > j += i; > } > > There are two "error" in it: main() doesn't have a return > type assigned, so per standard (int) will be assumed. And > there is no return statement. > > Compiler is system's gcc (older system, obviously): > > % cc -Wall -o returntest returntest.c > returntest.c:1: warning: return type defaults to 'int' > returntest.c: In function 'main': > returntest.c:5: warning: control reaches end of non-void function > > This is what we expect. > > But the program can be run, and we see: > > % ./returntest ; echo $? > 99 > > The return code is somehow assigned to the 'i' variable. > Why? Probably because it's stored in a register, and this > register is being used by the exit() and _exit() chain to > represent the return code. > > Funnily, when the program is modified: > > main() { > int i, j; > for(i = 0, j = 0; i > -100; i--) > j += i; > } > > The compiler warnings are the same. This is the result now: > > % ./returntest ; echo $? > 157 Not funnily, indicatively; 157 = 0x9d. -99 = 0xffffff9d, as an int. Exit codes would thus appear to be truncated to 0-255 unsigned. If you swapped assignments of i and j, I suspect you may get the unsigned value of the low byte of j as exit code instead? > None of them looks like an implicit "return 0;". I am not > judging Harbison & Steele, I'm just observing things. :-) Real Code beats 'should' every time :) Thanks for this, and your earlier reply. Of course, one could track down which register it is by disassembling the binary or - likely easier - by asking $CC for a listing, if it goes as far as exiting without heading off into a library call .. but I'm not going down that rabbit hole for mere curiosity :) cheers, Ian