Are destructors run when calling exit()?
No, most destructors are not run on exit()
.
C++98 §18.3/8 discusses this.
Essentially, when exit
is called static objects are destroyed, atexit
handlers are executed, open C streams are flushed and closed, and files created by tmpfile
are removed. Local automatic objects are not destroyed. I.e., no stack unwinding.
Calling abort
lets even less happen: no cleanup whatsoever.
How to properly call destructors when exiting within a thread?
It is the thread that calls exit
that does all of the cleanup.
Several cleanup steps are performed:
- The destructors of objects with thread local storage duration that are associated with the current thread, the destructors of objects with static storage duration, and the functions registered with std::atexit are executed concurrently
(emphasis added)
I thought the destructor would be called by the main thread
What makes you think that? C++ does not associate objects with threads. Even a thread local object can be interacted with on another thread through a pointer or reference.
Is there a way to keep the
exit(0)
call at the lowest level
Yes, don't have static duration std::thread
(sub-)objects, especially those which can call exit
.
with the destructors being called from the main thread?
Co-ordinate such that the main thread is the one to call exit
. Or just return from main
Will exit() or an exception prevent an end-of-scope destructor from being called?
If you call exit
, the destructor will not be called.
From the C++ standard (§3.6.1/4):
Calling the function
void exit(int);
declared in
<cstdlib>
(18.3) terminates the program without leaving the current block and hence without destroying any objects with automatic storage duration (12.4). If exit is called to end a program during the destruction of an object with static storage duration, the program has undefined behavior.
Are Basic Object Destructors Called On Exit()?
According to this link, it does not clean up the object.
Note that if you use non-stack memory, it will call the destructor:
static employee emp1;
Second note. Any time you are using cout
for debugging edge cases, timing critical debugging, etc., you should add a cout.flush()
right after the cout
to ensure your output is printed before it moves on. I have seen many people use cout
for debugging crashes and the output never prints because the program terminates before the OS had a chance to print the output.
Why does `std::exit` not trigger destructors as expected?
Objects with thread storage duration are guaranteed to be destroyed only for the thread which calls exit
. Quoting C++14 (N4140), [support.start.term] 18.5/8 (emphasis mine):
[[noreturn]] void exit(int status)
The function
exit()
has additional behavior in this International Standard:
- First, objects with thread storage duration and associated with the current thread are destroyed.
Next, objects with static storage duration are destroyed and functions registered by calling atexit
are called. See 3.6.3 for the order of destructions and calls. (Automatic objects are not
destroyed as a result of callingexit()
.)
If control leaves a registered function called byexit
because the function does not provide a
handler for a thrown exception,std::terminate()
shall be called (15.5.1).- Next, all open C streams (as mediated by the function signatures declared in
<cstdio>
) with
unwritten buffered data are flushed, all open C streams are closed, and all files created by calling
tmpfile()
are removed.- Finally, control is returned to the host environment. If status is zero or
EXIT_SUCCESS
, an
implementation-defined form of the status successful termination is returned. If status isEXIT_FAILURE
, an implementation-defined form of the status unsuccessful termination is returned.
Otherwise the status returned is implementation-defined.
The standard therefore does not guarantee destruction of objects with thread storage duration associated with other threads than the one calling exit
.
Is it safe to call exit() from a C++ function to terminate the program?
Some claim that exit() terminates the program normally, just as a return 0; would from main
std::exit
gets called anyway, as part of standard application lifecycle. Quote from CPPReference:
Returning from the main function, either by a return statement or by
reaching the end of the function performs the normal function
termination (calls the destructors of the variables with automatic
storage durations) and then executes std::exit, passing the argument
of the return statement (or 0 if implicit return was used) as
exit_code.
Others claim that exit() doesn't call all the destructors, etc
It's true, but it doesn't cancel the first statement. I.e. if destructors of you classes don't have any side effects that can survive the program, it doesn't matter whether local were destroyed properly or not, since entire memory of your process is freed after program termination. std::exit
however calls destructors of objects with static and thread local storage duration:
The destructors of objects with thread local storage duration that are
associated with the current thread, the destructors of objects with
static storage duration, and the functions registered with std::atexit
are executed concurrently
Destructors called upon program termination
It depends on how your program terminates. If it terminates by having main return (either by an explicit return or falling off the end), then yes, any automatic objects in main will be destructed.
But if your program terminates by calling exit(), then main doesn't actually go out of scope and any automatic objects will not be destructed.
Why aren't destructors guaranteed to be called on interpreter exit?
I'm not convinced by the previous answers here.
Firstly note that the example given does not prevent __del__
methods being called during exit. In fact, the current CPythons will call the __del__
method given, twice in the case of Python 2.7 and once in the case of Python 3.4. So this can't be the "killer example" which shows why the guarantee is not made.
I think the statement in the docs is not motivated by a design principle that calling the destructors would be bad. Not least because it seems that in CPython 3.4 and up they are always called as you would expect and this caveat seems to be moot.
Instead I think the statement simply reflects the fact that the CPython implementation has sometimes not called all destructors on exit (presumably for ease of implementation reasons).
The situation seems to be that CPython 3.4 and 3.5 do always call all destructors on interpreter exit.
CPython 2.7 by contrast does not always do this. Certainly __del__
methods are usually not called on objects which have cyclic references, because those objects cannot be deleted if they have a __del__
method. The garbage collector won't collect them. While the objects do disappear when the interpreter exits (of course) they are not finalized and so their __del__
methods are never called. This is no longer true in Python 3.4 after the implementation of PEP 442.
However, it seems that Python 2.7 also does not finalize objects that have cyclic references, even if they have no destructors, if they only become unreachable during the interpreter exit.
Presumably this behaviour is sufficiently particular and difficult to explain that it is best expressed simply by a generic disclaimer - as the docs do.
Here's an example:
class Foo(object):
def __init__(self):
print("Foo init running")
def __del__(self):
print("Destructor Foo")
class Bar(object):
def __init__(self):
print("Bar1 init running")
self.bar = self
self.foo = Foo()
b = Bar()
# del b
With the del b
commented out, the destructor in Foo
is not called in Python 2.7 though it is in Python 3.4.
With the del b
added, then the destructor is called (at interpreter exit) in both cases.
Related Topics
After Sending a Lot, My Send() Call Causes My Program to Stall Completely. How Is This Possible
Math Interface VS Cmath in C++
Using Memory Sanitizer with Libstdc++
Copy Constructor of Derived Qt Class
Create Objects in Conditional C++ Statements
In C/C++, Are Volatile Variables Guaranteed to Have Eventually Consistent Semantics Betwen Threads
How to Stop Windows from Blocking the Program During a Window Drag or Menu Button Being Held Down
Emplace an Aggregate in Std::Vector
Why Compile Error with Enable_If
Access Violation Writing Location 0Xcccccccc
Use Static_Assert to Check Types Passed to MACro
Array[Byte] to Hbitmap or Cbitmap
Finding C++ Interval Tree Algorithm Implementation
What Happens When Calling the Destructor of a Thread Object That Has a Condition Variable Waiting
Given a Start and End Point, and a Distance, Calculate a Point Along a Line
C++ Error on Ms Visual Studio: "Windows Has Triggered a Breakpoint in Javaw.Exe"