daveh@marob.MASA.COM (Dave Hammond) (12/14/88)
Can anyone explain why the statement: exit(0); /* followed immediately by main's closing brace */ causes lint to complain: ma-main.c ============== (137) warning: main() returns random value to invocation environment [yes, "exit(0)" is the statement on line 137 of the file ma-main.c] -- Dave Hammond UUCP: uunet!masa.com!{dsix2,marob}!daveh DOMAIN: dsix2!daveh@masa.com
earleh@eleazar.dartmouth.edu (Earle R. Horton) (12/14/88)
In article <416@marob.MASA.COM> daveh@marob.masa.com (Dave Hammond) writes: >Can anyone explain why the statement: > > exit(0); /* followed immediately by main's closing brace */ > >causes lint to complain: > >ma-main.c >============== >(137) warning: main() returns random value to invocation environment Syntactically, "exit(0)" is a function call. How the heck do you expect lint to know that exit() never returns? Since main() is usually declared to be of type int, then lint is fully justified in expecting to see a "return <something>" at the end of main(). You will have to either live with the lint warning, or cause main() to return something. How about: return(exit(0)); } That should keep lint happy! Earle R. Horton. 23 Fletcher Circle, Hanover, NH 03755 (603) 643-4109 Graduate student.
grs@alobar.ATT.COM (Gregg Siegfried) (12/15/88)
In article <416@marob.MASA.COM> daveh@marob.masa.com (Dave Hammond) writes: >Can anyone explain why the statement: > exit(0); /* followed immediately by main's closing brace */ >causes lint to complain: >(137) warning: main() returns random value to invocation environment Exit is not part of the C language and appears to lint (and the compiler) as just another function call. That it happens to free resources, close files, and run down the process is just a handy coincidence. ;-) To nuke this message, use return rather than exit. In most Unix environments, an implicit exit is linked in with crt0 anyway. >Dave Hammond Gregg Siegfried grs@alobar.att.com
gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/15/88)
In article <416@marob.MASA.COM> daveh@marob.masa.com (Dave Hammond) writes: >Can anyone explain why the statement: > exit(0); /* followed immediately by main's closing brace */ >causes lint to complain: >(137) warning: main() returns random value to invocation environment "lint" doesn't know that exit() never returns. Put /*NOTREACHED*/ after exit to tell "lint" this. This discussion occurred only a few months ago..
gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/15/88)
In article <11467@dartvax.Dartmouth.EDU> earleh@eleazar.dartmouth.edu (Earle R. Horton) writes: > How about: > return(exit(0)); Nope; that's a cure worse than the disease. exit() should be properly declared as having void result type (otherwise, "lint" should complain about THAT), and you cannot return a void expression.
guy@auspex.UUCP (Guy Harris) (12/16/88)
> exit(0); /* followed immediately by main's closing brace */ > >causes lint to complain: > >(137) warning: main() returns random value to invocation environment See the other article in comp.lang.c/INFO-C about "incorrect" "lint" complaints; the problem is the same - "lint" has no idea that "exit" never returns, and therefore thinks that after it *does* return, "main" returns by "falling off the end". This means it doesn't return a value; in many C implementations, returning from "main" with a particular value causes the process to terminate with the returned value as its exit status. To fix this, either change exit(0); to return 0; (with parentheses added as per local preferences) or add /*NOTREACHED*/ after the "exit(0)".
rbutterworth@watmath.waterloo.edu (Ray Butterworth) (12/16/88)
In article <416@marob.MASA.COM>, daveh@marob.MASA.COM (Dave Hammond) writes: > Can anyone explain why the statement: > exit(0); /* followed immediately by main's closing brace */ > causes lint to complain: > (137) warning: main() returns random value to invocation environment If your <stdlib.h> doesn't have something like "extern void /*GOTO*/ exit();" in it (not many do), then your lint doesn't know that exit() never returns. In that case, you have to code your example as: ... exit(0); /*NOTREACHED*/ } Most versions of lint take this comment to mean that it should pretend that it had just processed an unconditional goto. The big disadvantage of NOTREACHED is that lint will only tell you something useful if you use it correctly, rather than if you forget to use it (e.g. exit(0); x=5; return x;). The disadvantage of NOTREACHED and GOTO is that the compiler can't recognize them and use the knowledge to optimize the code. Overloading a keyword, as in "extern goto exit();" in a header file would be an ideal solution, but as you can probably guess: that's not C.
ok@quintus.uucp (Richard A. O'Keefe) (12/16/88)
In article <1037@alobar.ATT.COM> grs@alobar.ATT.COM (Gregg Siegfried) writes: >In article <416@marob.MASA.COM> daveh@marob.masa.com (Dave Hammond) writes: >>Can anyone explain why the statement: >> exit(0); /* followed immediately by main's closing brace */ >>causes lint to complain: >>(137) warning: main() returns random value to invocation environment Note that exit() can be called *anywhere*, not just in main(). In particular, it can legitimately be called in functions which do NOT return 'int' (e.g. many of my report-error-and-drop-dead functions are declared 'void'), so the "return exit(0)" kludge that two posters have suggested so far really isn't a very good idea. If you read the lint documentation you will find that it understands some special comments. In particular, the way to handle things like exit() and longjmp() is exit(0); /*NOTREACHED*/ which is reasonably clear to human readers as well.
logan@vsedev.VSE.COM (James Logan III) (12/17/88)
In article <416@marob.MASA.COM> daveh@marob.masa.com (Dave Hammond) writes: # Can anyone explain why the statement: # # exit(0); /* followed immediately by main's closing brace */ # # causes lint to complain: # # ma-main.c # ============== # (137) warning: main() returns random value to invocation environment Lint does not realize that exit() does not return control back to the function main(). Since you don't have "return <value>" as the last statement, Lint thinks the return value of main() would be undefined. If you want lint to stop whining about it, change the last few lines to: exit(0); /*NOTREACHED*/ } Don't ask me to give you a good reason for why lint doesn't know about exit(); there is none. -Jim -- Jim Logan logan@vsedev.vse.com (703) 892-0002 uucp: ..!uunet!vsedev!logan inet: logan%vsedev.vse.com@uunet.uu.net
john@frog.UUCP (John Woods) (12/19/88)
In article <1037@alobar.ATT.COM>, grs@alobar.ATT.COM (Gregg Siegfried) writes: > In article <416@marob.MASA.COM> daveh@marob.masa.com (Dave Hammond) writes: > >Can anyone explain why the statement: > > exit(0); /* followed immediately by main's closing brace */ > >causes lint to complain: > >(137) warning: main() returns random value to invocation environment >To nuke this message, use return rather than exit. Even better is: main() { do_something_important(); exit(0); /* NOTREACHED */ } the /* NOTREACHED */ lint directive instructs lint as to exactly what is going on. It also instructs the reader as to exactly what is going on. It would have been nice if lint could have been taught that lint-library functions with a definition something like void exit(n) int n; { /* NOTREACHED */ } will never return, but on the other hand, making that manifest for the reader in the place of use has benefits. -- John Woods, Charles River Data Systems, Framingham MA, (508) 626-1101 ...!decvax!frog!john, john@frog.UUCP, ...!mit-eddie!jfw, jfw@eddie.mit.edu Go be a `traves wasswort. - Doug Gwyn
sme@computing-maths.cardiff.ac.uk (Simon Elliott) (12/19/88)
In article <11467@dartvax.Dartmouth.EDU>, earleh@eleazar.dartmouth.edu (Earle R. Horton) writes: > In article <416@marob.MASA.COM> daveh@marob.masa.com (Dave Hammond) writes: > >Can anyone explain why the statement: > > exit(0); /* followed immediately by main's closing brace */ > >causes lint to complain: > >(137) warning: main() returns random value to invocation environment > [discussion deleted] > How about: > return(exit(0)); > } Well, in my manual (Section 2: 'Lint, a C Program Checker' by S.C.Johnson) there is a section entitled 'Shutting Lint Up', with a comment to the effect that sometimes the programmer is smarter than lint. Following is a discussion of the directives (syntactically comments) that a programmer can use to let lint know that the programmer really knows what (s)he is doing. Among these are: /*VARARGS*/ preceding a function definition, to let lint know it shouldn't complain about variable numbers of arguments to calls of the following function. /*NOTREACHED*/ to let lint know that a particular spot in the code is never executed. There are several more such directives. -- -------------------------------------------------------------------------- Simon Elliott Internet: sme%v1.cm.cf.ac.uk@cunyvm.cuny.edu UWCC Computer Centre JANET: sme@uk.ac.cf.cm.v1 40/41 Park Place UUCP: {backbones}!mcvax!ukc!reading!cf-cm!sme Cardiff, Wales PHONE: +44 222 874300
stuart@bms-at.UUCP (Stuart Gathman) (12/20/88)
In article <416@marob.MASA.COM>, daveh@marob.MASA.COM (Dave Hammond) writes: > Can anyone explain why the statement: > exit(0); /* followed immediately by main's closing brace */ > causes lint to complain? Lint does not know that exit(int) is an example of a 'goto' function, i.e. a function that never returns. Someone suggested on the net that 'goto' should be used in a manner similar to 'void' in function declarations of exit(), longjmp(), and friends to indicate this. The compiler could then generate better code (use goto instead of call, don't bother popping arguments, no need to flush cached variables, etc.). For now, lint recognizes a magic comment, "/*NOTREACHED*/" which should follow exit() in your example. -- Stuart D. Gathman <stuart@bms-at.uucp> <..!{vrdxhq|daitc}!bms-at!stuart>
aaron@satco.UUCP (Aaron Pelton) (12/20/88)
In article <719@auspex.UUCP>, guy@auspex.UUCP (Guy Harris) writes: > > > exit(0); /* followed immediately by main's closing brace */ > >causes lint to complain: > >(137) warning: main() returns random value to invocation environment > > status. To fix this, either change > exit(0); > to > return 0; > (with parentheses added as per local preferences) or add > /*NOTREACHED*/ > after the "exit(0)". This raises the question of what return does at the end of main as opposed to what exit does. It is stated that exit() does assorted cleanup jobs. return seems only to be specified as exiting a function. Given the following: main() { printf("hello world\n"); exit(0); } and the same with return(0) in place of exit, I came up with a grand total of four lines difference in asm code. exit() seemed to be called in both cases. Is exit() garuanteed to be called on exit of a program with return? Is there any inherent advantage of exit() over return for exiting main? Is there any danger in randomly switching from one to the other? -- Aaron Pelton | If it sounds like an opinion, it's probably mine. aaron@satco.UUCP | Only R. Crusoe could have it all done by Friday {decvax,uunet}!virgin!satco!aaron | So much for self taught C programming.....
guy@auspex.UUCP (Guy Harris) (12/21/88)
> Is exit() garuanteed to be called on exit of a program with return? All the UNIX C implementations I know of call "exit()" if you return from "main()". I think the dpANS explicitly requires this. > Is there any inherent advantage of exit() over return for exiting > main? In dpANS C, and in any implementation that, when the ANS comes out, is conformant to the ANS, no. The return value of "main" is the exit status passed to "exit()". In some UNIX C implementations, yes; returning from "main()" always causes "exit()" to be called with an argument of 0. (This is true in SunOS releases from 2.0 to 3.5, I think; this was fixed in 4.0. I remember somebody claiming it was true of some Amdahl UTS release as well.) In non-UNIX releases, it may also be true; I don't know which of them either 1) cause "exit()" to be called if you return from "main()" or 2) use the return value of "main()" as the argument to "exit()". > Is there any danger in randomly switching from one to the other? "Randomly"? As in if (rand() & 0x80) exit(1); else return 1; If you know your code is always going to be built and run on an implementation that does it right, no, they're equivalent. Otherwise, "exit()" is safer.
karl@haddock.ima.isc.com (Karl Heuer) (12/21/88)
In article <138@bms-at.UUCP> stuart@bms-at.UUCP (Stuart Gathman) writes: >Someone suggested on the net that 'goto' should be used in a manner similar >to 'void' in function declarations of exit(), longjmp(), and friends ... I agree with the concept, but I think that overloading yet another keyword would be a big mistake. >The compiler could then generate better code (use goto instead of call, don't >bother popping arguments, no need to flush cached variables, etc.). Note that some of these optimizations would not always be legal if the function is longjmp(), or any function which might call longjmp(). Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
jeff@amsdsg.UUCP (Jeff Barr) (12/22/88)
In article <11467@dartvax.Dartmouth.EDU>, earleh@eleazar.dartmouth.edu (Earle R. Horton) writes: > In article <416@marob.MASA.COM> daveh@marob.masa.com (Dave Hammond) writes: > >Can anyone explain why the statement: > > > > exit(0); /* followed immediately by main's closing brace */ > > > >causes lint to complain: > > > >ma-main.c > >============== > >(137) warning: main() returns random value to invocation environment > How about: void main () { ... exit (0); } Jeff -- /-------------------------------------------------------\ / Jeff Barr AMS-DSG uunet!amsdsg!jeff 800-832-8668 \ \ American Express: "Don't leave $HOME without it". / \-------------------------------------------------------/
guy@auspex.UUCP (Guy Harris) (12/22/88)
>How about: > > void main () ... Doesn't help (I tried it), and isn't correct anyway. The dpANS indicates, as I remember, that "main" is expected (at least in a hosted environment) to return an "int", and that if "main" returns "exit" is then called with its return value as an argument.
karl@haddock.ima.isc.com (Karl Heuer) (12/23/88)
In article <179@amsdsg.UUCP> jeff@amsdsg.UUCP (Jeff Barr) writes: >> >(137) warning: main() returns random value to invocation environment >How about: > void main () { ... exit (0); } (a) It doesn't work, at least on the machine I tried. (b) According to the dpANS, the type of `main' must be either `int(void)' or `int(int, char **)'. A `void' declaration, although logically correct, cannot be used in a strictly conforming program. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/27/88)
In article <179@amsdsg.UUCP> jeff@amsdsg.UUCP (Jeff Barr) writes: >How about: > void main () > { > ... Don't do this! Declare your types properly! Whatever is calling main() is expecting it to have a certain "shape" (that of a function with two arguments and returning an int); ANSI C requires that the compiler be able to compensate for the arguments being omitted, but not for the return type being garbled.
dave@micropen (David F. Carlson) (12/28/88)
In article <782@auspex.UUCP>, guy@auspex.UUCP (Guy Harris) writes: > >How about: > > > > void main () > ... > > Doesn't help (I tried it), and isn't correct anyway. The dpANS > indicates, as I remember, that "main" is expected (at least in a hosted > environment) to return an "int", and that if "main" returns "exit" is > then called with its return value as an argument. int main() { .... if (blah) exit(-1); ... return( 0 ); } I have solved this "problem" by not using the function exit() to return to the calling environment main() status. Rather, use return at the end of main(). Lint seems to like return from functions. It never has been able to deal with exit() properly, ("statement not reached", etc.) so why try? -- David F. Carlson, Micropen, Inc. micropen!dave@ee.rochester.edu "The faster I go, the behinder I get." --Lewis Carroll
badri@valhalla.ee.rochester.edu (Badri Lokanathan) (12/28/88)
In article <599@micropen>, dave@micropen (David F. Carlson) writes: > I have solved this "problem" by not using the function exit() to return > to the calling environment main() status. Rather, use return at the end > of main(). Lint seems to like return from functions. It never has been > able to deal with exit() properly, ("statement not reached", etc.) so why > try? > Alas, some of us (at least I) have gotten used to the easy clean up facility that exit() provides. That is, flushing all I/O buffers and closing them. return(status) works cleanly if the programmer takes care of this. I have personally not had this problem with return/exit in lint, so I shall continue to use exit (maybe I should use egress as PT Barnum once did :-) -- "I care about my fellow man {) badri@ee.rochester.edu Being taken for a ride, //\\ {ames,cmcl2,columbia,cornell, I care that things start changing ///\\\ garp,harvard,ll-xn,rutgers}! But there's no one on my side."-UB40 _||_ rochester!ur-valhalla!badri
nevin1@ihlpb.ATT.COM (Liber) (12/28/88)
In article <11274@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes: >(b) According to the dpANS, the type of `main' must be either `int(void)' or >`int(int, char **)'. A `void' declaration, although logically correct, cannot >be used in a strictly conforming program. It is only logically correct when exit() is "reachable" from all possible executions of main(). It may not be logically correct if someone recursively calls main() and expects a return value. What value main() returns and if main() calls some funky function so that it never returns are two different issues. -- NEVIN ":-)" LIBER AT&T Bell Laboratories nevin1@ihlpb.ATT.COM (312) 979-4751
bill@twwells.uucp (T. William Wells) (12/29/88)
In article <599@micropen> dave@micropen (David F. Carlson) writes:
: I have solved this "problem" by not using the function exit() to return
: to the calling environment main() status. Rather, use return at the end
: of main(). Lint seems to like return from functions. It never has been
: able to deal with exit() properly, ("statement not reached", etc.) so why
: try?
Try putting /*NOTREACHED*/ after the exit(). That shuts up every lint
I know about. It's in the manual.
---
Bill
{uunet|novavax}!proxftl!twwells!bill
bill@twwells.uucp (T. William Wells) (12/29/88)
In article <1700@valhalla.ee.rochester.edu> badri@valhalla.ee.rochester.edu (Badri Lokanathan) writes: : Alas, some of us (at least I) have gotten used to the easy clean up facility : that exit() provides. That is, flushing all I/O buffers and closing : them. return(status) works cleanly if the programmer takes care of : this. I have personally not had this problem with return/exit in lint, so I : shall continue to use exit (maybe I should use egress as PT Barnum once : did :-) Returning from main does all these things on every system I know of. In other words, main() { ... return (0); } and main() { ... exit(0); } are pretty much equivalent. Generally, main is called from another routine which, besides setting up the C run-time environment, does something like: crt0(argc, argv) { exit(main(argc, argv)); } The only exception that I know of to this are systems, like certain versions of SunOS, that behave more like: crt0(argc, argv) { main(argc, argv); exit(0); } --- Bill {uunet|novavax}!proxftl!twwells!bill
chris@mimsy.UUCP (Chris Torek) (12/30/88)
This has been mentioned before but I had better do it again: >In article <599@micropen> dave@micropen (David F. Carlson) writes: >>... Rather, use return at the end of main(). In article <1700@valhalla.ee.rochester.edu> badri@valhalla.ee.rochester.edu (Badri Lokanathan) writes: >Alas, some of us (at least I) have gotten used to the easy clean up facility >that exit() provides. That is, flushing all I/O buffers and closing >them. return(status) works cleanly if the programmer takes care of this. In what the dpANS calls a hosted environment---that is, in all the interesting cases; in freestanding environments like a Unix kernel, one generally cannot exit at all---return(expr) from main and exit(expr) have identical effects. The startup code that calls main reads, essentially, exit(main(argc, argv, envp)); There are a few exceptions, notably some versions of SunOS. These read (void) main(argc, argv, envp); exit(0); so that return(expr) from main is the same as exit(0). There should never be any difference between main() { return (0); } and main() { exit(0); } even on the buggiest implementations around. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
mcdonald@uxe.cso.uiuc.edu (12/30/88)
>In what the dpANS calls a hosted environment---that is, in all the >interesting cases; in freestanding environments like a Unix kernel, >one generally cannot exit at all---return(expr) from main and >exit(expr) have identical effects. There are, in the PC world, cases of non-hosted environments that are relatively common - programs run under Microsoft Windows and the OS/2 presentation manager are non-hosted environments. They don't have main() at all. No argv and argc. And many of the standard library routines don't work (getc and putc are missing, for example). I think that they are certainly "interesting". Sickening, but interesting. Doug McDonald P.S. Inside a MS Windows program, it would be possible to write the various subroutines and call a "main" in the usual way. For some odd reason they haven't done it.
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/02/89)
In article <1700@valhalla.ee.rochester.edu> badri@valhalla.ee.rochester.edu (Badri Lokanathan) writes: >Alas, some of us (at least I) have gotten used to the easy clean up facility >that exit() provides. That is, flushing all I/O buffers and closing >them. return(status) works cleanly if the programmer takes care of >this. Oh, come on. Return from main() is ALSO supposed to do this; it's practically like a coroutine jump to exit() with the return value being passed to exit as its argument. The real problem comes when you try to return a non-zero termination status via "return N;" from main() on a system like some releases of SunOS where the run-time start-off code has been "hot wired" to force an exit(0) whenever main returns. That was a mistake that needs to be fixed, but small consolation if it bites you.
msb@sq.uucp (Mark Brader) (01/05/89)
[If you see two versions of this, it's not my fault, I cancelled the first.] To a comment about: > > ... easy clean up facility > > that exit() provides. That is, flushing all I/O buffers and closing > > them. return(status) works cleanly if the programmer takes care of > > this. Doug Gwyn replies: > Oh, come on. Return from main() is ALSO supposed to do this; it's > practically like a coroutine jump to exit() with the return value > being passed to exit as its argument. Personally I prefer to think of it as "It's as if the system started the program by calling exit(main(...));", but it amounts to the same thing. However, in a later article Doug says: > exit(), which on systems conforming to the C > standard will flush STDIO buffers and invoke any functions registered > via atexit() ... And this tips us to his unstated assumption. Doug is talking about ANSI C, which doesn't quite exist yet. (Nearly -- the draft has been finalized and submitted to X3, I hear tell -- but not yet.) In the meantime, we can't strictly call an implementation wrong if it complies with the original C Reference Manual -- K&R appendix A. And that Appendix doesn't mention main() at all, let alone the return from main(). For that matter, it doesn't mention exit() either. Status returns through the argument of exit() *are* mentioned in the (tutorial) body of the book, but the return from main() is not mentioned there either. So systems where the return from main() is not equivalent to exit() are not exactly wrong -- only old-fashioned, and soon to be nonstandard. In the meantime, the cautious programmer will call exit(). Actually, in all of the foregoing I should speak of the return from the *initial* call of main(). [Reference in draft standard: section 2.1.2.2] The function could also be called recursively, and a return from an inner call is in no way special. Mark Brader "... one of the main causes of the fall of SoftQuad Inc., Toronto the Roman Empire was that, lacking zero, they utzoo!sq!msb had no way to indicate successful termination msb@sq.com of their C programs." -- Robert Firth