Return vs exit on FreeBSD / bin / and / usr / bin

I noticed that the FreeBSD code in /bin and /usr/bin has some fix for using exit instead of return , what does this mean?

All I have in mind is that the return can damage the vfork(2) stack frame, is this the only reason? If this is true, then why only part of the commands in /bin and /usr/bin received corrections, and not all of them?

+5
source share
3 answers

According to 5.1.2.2.3p1

If the return type of the main function is int compatible, returning from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as an argument

This rules out your corrupt theory of stack frames; return 0; functionally identical exit(0); to match C implementations (at least for non-recursive main entry points).

I would suggest that this change was simply stylistic or perhaps guided by ignorance. Another possibility is that the author has a desire to convert main into a recursive function (or main has already been turned into a recursive function; idk, I just did a quick grep and it doesn't seem immediately recursive). Finally, as a final grim alternative, perhaps the C implementation used by FreeBSD is inappropriate (I hope not!) ...

edit . It just occurred to me to read this answer that it could be a workaround for a compiler error, but, alas, I checked the source code for using atexit and did not find any reason to continue this line of reasoning.

+1
source

Let's see if I can combine the various links provided by others into an appropriate answer.


As for the C language, there is no difference.

Calling exit() calls

  • calling functions registered with atexit() ;
  • cleans and closes output streams;
  • deletes files opened with tmpfile() ;
  • returns control to the environment.

A return <n> from main is equivalent to exit( <n> ) .


Some erroneous static code analyzers think differently.

As for the C language, the memory leak allocated by main() , not free() d. Unix cleans up at the end of the process, but not all operating systems (!).

Apparently, some static code analyzers believe that the memory still allocated at exit() was not skipped (while they do for return from main() ) , therefore this commit was done (to get rid of the warning )

This is a workaround for errors in the code analyzer.


As for the C ++ language, there is a big difference.

When you return from main() , you leave the scope, which means that local objects will be destroyed.

Since C ++ programmers take advantage of deterministic destruction (unlike, for example, Java, which could or could not execute your destructor even when VM was finished ...), they usually do their destructors more than just freeing up memory. Network connections, temporary files, terminal windows blocked with ncurses are all good that C programmers will have to take care of them manually or use atexit() for.

When you call std::exit() from main() , this function directly transfers control at runtime. The main() function never returns, the process ends without calling the main() -local object destructors.

In addition, while std::exit() is defined as hiding and closing C output streams, there is no such condition for C ++ streams.

+1
source

In my opinion, not a good reason for this.

This specific change is discussed in this post on the freebsd mailing list.

The story that the commit log should be

"Use exit () instead of returning to main () to work with a broken static analyzer"

Thus, it will help static analyzers and memory analyzers, which would otherwise report materials allocated in main () as a memory leak, that most simple utilities do not interfere with de-allocation, since the process is going to exit anyway.

0
source

Source: https://habr.com/ru/post/1235768/


All Articles