Reputation: 12110
Is there a difference between using exit()
or just return
statements in main()
?
Personally I favor the return
statements because I feel it's like reading any other function and the flow control when I'm reading the code is smooth (in my opinion). And even if I want to refactor the main()
function, having return
seems like a better choice than exit()
.
Does exit()
do anything special that return
doesn't?
Upvotes: 234
Views: 92883
Reputation: 7129
There actually IS a difference between exit(0)
and return(0)
in main
– when your main
function is called multiple times.
The following program
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
if (argc == 0)
return(0);
printf("%d", main(argc - 1, argv));
}
Run as
./program 0 0 0 0
Will result in following output:
00000
However this one:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
if (argc == 0)
exit(0);
printf("%d", main(argc - 1, argv));
}
Won't print anything regardless of the arguments.
If you are sure that nobody will ever call your main
explicitly it is not technically a big difference in general, but to maintain clearer code exit
would look much better. If you for some reason want to call main
– you should adjust it to your needs.
Speaking about C.
Upvotes: -1
Reputation: 223719
In C returning from main
is exactly the same as calling exit
with the same value.
Section 5.1.2.2.3 of the C standard states:
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.
The rules for C++ are a bit different as mentioned in other answers.
Upvotes: 0
Reputation: 47954
Does exit() do anything special that 'return' doesn't?
With some compilers for uncommon platforms, exit()
might translate its argument into your program's exit value while a return from main()
might just pass the value directly to the host environment without any translation.
The standard requires identical behavior in these cases (specifically, it says returning something that's int
-compatible from main()
should be equivalent to calling exit()
with that value). The problem is that different OSes have different conventions for interpreting the exit values. On many (MANY!) systems, 0 means success and anything else is a failure. But on, say, VMS, odd values mean success and even ones mean failure. If you returned 0 from main()
, a VMS user would see a nasty message about an access violation. There wasn't actually an access violation--that was simply the standard message associated with failure code 0.
Then ANSI came along and blessed EXIT_SUCCESS
and EXIT_FAILURE
as arguments you could pass to exit()
. The standard also says that exit(0)
should behave identically to exit(EXIT_SUCCESS)
, so most implementations define EXIT_SUCCESS
to 0
.
The standard, therefore, puts you in a bind on VMS, as it leaves no standard way to return a failure code that happens to have the value 0.
The early-1990s era VAX/VMS C compiler therefore did not interpret the return value from main()
, it simply returned whatever value to the host environment. But if you used exit()
it would do what the standard required: translate EXIT_SUCCESS
(or 0
) into a success code and EXIT_FAILURE
into a generic failure code. To use EXIT_SUCCESS
, you had to pass it to exit()
, you could not return it from main()
. I don't know whether more modern versions of that compiler preserved that behavior.
A portable C program used to look like this:
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Hello, World!\n");
exit(EXIT_SUCCESS); /* to get good return value to OS */
/*NOTREACHED*/ /* to silence lint warning */
return 0; /* to silence compiler warning */
}
Aside: If I recall correctly, the VMS convention for exit values is more nuanced than odd/even. It actually uses something like the low three bits to encode a severity level. Generally speaking, however, the odd severity levels indicated success or miscellaneous information and the even ones indicated errors.
Upvotes: 5
Reputation: 29597
Another difference:
exit
is a Standard Library
function so you need to include
headers and link with the standard
library. To illustrate (in C++),
this is a valid program:
int main() { return 0; }
but to use exit
you'll need an include:
#include <stdlib.h>
int main() { exit(EXIT_SUCCESS); }
Plus this adds an additional assumption: that calling exit
from main
has the same side effects as returning zero. As others have pointed out, this depends on what kind of executable you're building (i.e., who's calling main
). Are you coding an app that uses the C-runtime? A Maya plugin? A Windows service? A driver? Each case will require research to see if exit
is equivalent to return
. IMHO using exit
when you really mean return
just makes the code more confusing. OTOH, if you really do mean exit
, then by all means use it.
Upvotes: 30
Reputation: 2792
I STRONGLY second the comment by R. about using exit() in order to avoid having automatic storage in main()
reclaimed before the program actually ends. A return X;
statement in main()
is not precisely equivalent to a call to exit(X);
, since the dynamic storage of main()
vanishes when main()
returns, but it it does not vanish if a call to exit()
is made instead.
Furthermore, in C or any C-like language a return
statement strongly hints to the reader that execution will continue in the calling function, and while this continuation of execution is usually technically true if you count the C startup routine which called your main()
function, it's not exactly what you mean when you mean to end the process.
After all, if you want to end your program from within any other function except main()
you must call exit()
. Doing so consistently in main()
as well makes your code much more readable, and it also makes it much easier for anyone to re-factor your code; i.e. code copied from main()
to some other function won't misbehave because of accidental return
statements that should have been exit()
calls.
So, combining all of these points together the conclusion is that it's a bad habit, at least for C, to use a return
statement to end the program in main()
.
Upvotes: 5
Reputation: 215201
There is at least one reason to prefer exit
: If any of your atexit
handlers refer to automatic-storage-duration data in main
, or if you used setvbuf
or setbuf
to assign to one of the standard streams an automatic-storage-duration buffer in main
, then returning from main
produces undefined behavior, but calling exit
is valid.
Another potential usage (usually reserved for toy programs, however) is to exit from a program with recursive invocations of main
.
Upvotes: 18
Reputation: 339786
I always use return
because the standard prototype for main()
says that it does return an int
.
That said, some versions of the standards give main
special treatment and assume that it returns 0 if there's no explicit return
statement. Given the following code:
int foo() {}
int main(int argc, char *argv[]) {}
G++ only generates a warning for foo()
and ignores the missing return from main
:
% g++ -Wall -c foo.cc
foo.cc: In function ‘int foo()’:
foo.cc:1: warning: control reaches end of non-void function
Upvotes: 5
Reputation: 8614
Actually, there is a difference, but it's subtle. It has more implications for C++, but the differences are important.
When I call return
in main()
, destructors will be called for my locally scoped objects. If I call exit()
, no destructor will be called for my locally scoped objects! Re-read that. exit()
does not return. That means that once I call it, there are "no backsies." Any objects that you've created in that function will not be destroyed. Often this has no implications, but sometimes it does, like closing files (surely you want all your data flushed to disk?).
Note that static
objects will be cleaned up even if you call exit()
. Finally note, that if you use abort()
, no objects will be destroyed. That is, no global objects, no static objects and no local objects will have their destructors called.
Proceed with caution when favoring exit over return.
http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a
Upvotes: 317