9

I'm reading this question and there is an answer that explains why using exit() is bad because:

  • You will end up having multiple exit points from the program
  • It makes code more convoluted (like using goto)
  • It cannot release memory allocated at runtime

I should clarify that I'm using Qt, so the code is already a bit "convoluted" since I'm taking advantage of signals and slots. That being said, for issue #1, I see it's related to #2, but my code currently attempts to avoid usage of exit() because I was told it would make my code look like a mess, but avoiding exit has made it a mess. I have functions that don't have to return anything, returning things. For example, when I have users register and their username already exists, instead of just calling exit() after telling the user registration has failed (which is the desired behavior in this situation) I return false to a function which then returns false to another function which then returns false to my main which then checks if that function returned true or false, and if it returns false then it returns 0. So much for avoiding exit() making the code clean.

For the third issue, doesn't using exit(0) tell the OS that the program is done running and the OS will free that memory by itself anyway? I ran a test case that uses exit(0) when I press a button and the process is removed from the process list and the memory is freed, so why is this even a concern? It seems it's an outright false statement, at least on Windows.

Community
  • 1
  • 1
ozzymado
  • 960
  • 3
  • 15
  • 26
  • The OS can't clean up everything. Imagine a destructor that terminates an online connection or one that flushes text to a log file. The OS is quite limited for what can happen in destructors. – chris Aug 05 '14 at 14:48
  • Straight from the comment on that answer: *exit() does not return. So no stack unwinding can take place. Not even global objects will get destroyed. But the functions registered with atexit() will be called.* – scohe001 Aug 05 '14 at 14:49
  • @Josh But that seems incorrect since I just tested it and the memory was cleared. – ozzymado Aug 05 '14 at 14:51
  • 3
    thats simply wrong - just about every OS out there will "clean" your resources as much as possible - sockets which are bound to a process will get destroyed, files will be closed and whatnot. But it CANT clean up potential, invalid data of your process - if it ended before it could write all of your data ... well ... quite obvious what will happen. – specializt Aug 05 '14 at 14:51
  • @specializt So as long as I make sure I only call exit when I can confirm I'm not doing anything I should be fine? With my registration example, I only return once I'm sure the registration failed anyway, so I can be completely certain there is no data being written. – ozzymado Aug 05 '14 at 14:53
  • Either that or I could just `flush` any streams that can potentially have data in them at the time of `exit`ing, which I think is much, much more elegant than having a long series of returns just to meet a standard. – ozzymado Aug 05 '14 at 15:04
  • 1
    yes - its pretty well-defined after that, most of the ancient ones (the people who created the first operating systems) used to create programs like this every day. Its called "procedural programming". Not very readable, somewhat error-prone, overall ugly and not advisable BUT it works. – specializt Aug 05 '14 at 15:05
  • @Lighthat: If you're certain you know *everything* that needs to be done to shut down the process correctly, and you're *certain* the code will never be modified so anything else needs to be done to shut down cleanly, then calling `exit` should be safe (but to meet those criteria, you have to pretty much know that the code is dead and waiting to be buried). – Jerry Coffin Aug 05 '14 at 15:08
  • It is unusual to close a question as a duplicate of a more recent one, but the new question has some excellent answers. – Jonathan Leffler May 16 '15 at 16:51
  • @JonathanLeffler: Yes, the new question has some good answers. It *does not*, however, show when and how a faster exit is possible and/or recommended. – Deduplicator Jul 19 '15 at 15:47
  • The forbidden use for `exit` is in libraries. If you ever need to use a library which calls exit then it will kill your program and never give you the chance to gracefully recover from that. Imagine a JSON parser library which calls `exit` if it fails for some reason, pretty bad! I've already had a dreadful experience with such library... – caiohamamura Nov 10 '20 at 15:40

2 Answers2

15

Just blindly calling exit() somewhere in your program is considered bad for a simple reason:

It does not properly shutdown other threads (they just get terminated), it does not properly flush all buffers (stdio files are flushed) and guarantee a consistent and valid state of permanent/shared resources (files/shared memory/other ways to communicate).

Still, if you can guarantee that no thread is running which might interfere (by being killed holding a lock or such), and all buffers which need it will be flushed by exit(), that's a valid way to achieve a faster shutdown.

Much modern software is programmed for even faster shutdown:

It is crash-tolerant, in that at nearly every time, just shutting down using e.g. _Exit() (not even calling atexit or at_quick_exit registered hooks) is ok. That is vastly faster than an ordered shutdown in most cases (Windows user interface resources should be destroyed first if possible, because they are an exception).

For further reading: Crash-only software (PDF!)

Crash-only programs crash safely and recover quickly. There is only one way to stop such software - by crashing it - and only one way to bring it up - by initiating recovery. Crash-only systems are built from crash-only components, and the use of transparent component-level retries hides intra-system component crashes from end users. In this paper we advocate a crash-only design for Internet systems, showing that it can lead to more reliable, predictable code and faster, more effective recovery. We present ideas on how to build such crash-only Internet services, taking successful techniques to their logical extreme.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
  • Which user interface resources have to be destroyed explicitly? Doesn't Windows reclaim all such objects after the process terminates? – Ruslan Aug 29 '19 at 14:33
  • @Ruslan Yes, Windows will reclaim them. But that is (or was?) slower than explicitly cleaning them up yourself. – Deduplicator Aug 29 '19 at 16:54
1

Items 1 and 2, I disagree with. Those are more matters of style and preference.

As to item 3, you should look at the documentation to see what it actually will or will not free or flush (http://en.cppreference.com/w/cpp/utility/program/exit and http://msdn.microsoft.com/en-us/library/6wdz5232.aspx). For instance, the MS documentation says "flushes all file buffers before it terminates the process."

When your program exits, the OS will reclaim the memory, but that's not what he's talking about. What he means is that resources like semaphores won't be released properly or in a timely fashion. Maybe it's a concern, maybe not, depending on what sort of resources you're using.

Rob K
  • 8,757
  • 2
  • 32
  • 36