I have the following code snippet:
#include<iostream>
using namespace std;
class Test {
public:
Test() { cout << "Constructor is executed\n"; }
~Test() { cout << "Destructor is executed\n";}
void show() { this->Test::~Test(); }
};
int main() {
Test t;
t.show();
return 0;
}
Here is the output:
Constructor is executed
Destructor is executed
Destructor is executed
Question: If t.show() has already called the destructor on "this" object(i.e. current object), which causes "destructor is executed" to be displayed once, then what causes it to be displayed for the second time? Which object is getting destroyed in that case ?
Automatic variables get destroyed when they go out of scope. Test t is an automatic variable which goes out of scope when main ends. That's the second time the destructor is being called. The first time is through Test::show since the function manually destroys the object pointed to by this.
Since, C++ follows the philosophy of not paying for what you don't use, there isn't a runtime check of any sort before invoking the destructor on automatic variables going out of scope. Of course, what actually happens on the second destructor call is UB. Beware of nasal demons.
Pradhan has given you an easy to understand explanation, I'll share the particular rule that deals with explicit destructor calls on objects with automatic storage duration, found in section 3.8p8 of the Standard:
If a program ends the lifetime of an object of type T with static, thread, or automatic storage duration and if T has a non-trivial destructor, the program must ensure that an object of the original type occupies that same storage location when the implicit destructor call takes place; otherwise the behavior of the program is undefined. This is true even if the block is exited with an exception.
You're violating this rule, so you get undefined behavior.
The "implicit destructor call" is described in 6.7p2:
Variables with automatic storage duration are initialized each time their declaration-statement is executed. Variables with automatic storage duration declared in the block are destroyed on exit from the
block.
Related
Does a destructor gets called before an object is destroyed or after an object is destroyed?
I think that it is called before an object is destroyed because after an object is destroyed we cant access that memory to free any resource in there but if I am wrong then please correct me so I can understand it well
#include <iostream>
#include <cassert>
#include <cstddef>
class Check
{
public:
int neu{};
Check() = default;
Check(int n)
{
neu = n;
}
void print()
{
std::cout << neu << std::endl;
}
~Check()
{
std::cout << "It has been destroyed "<<neu <<std::endl;
}
};
int main()
{
Check let,see(30);
let.print();
return 0;
// does destructor gets called here
} // or does destructor gets called herecode here
Does a destructor gets called before an object is destroyed or after an object is destroyed?
The lifetime of the object has ended when the destructor is called. The object is destroyed by the destructor.
// does destructor gets called here
} // or does destructor gets called herecode here
There's really no practical difference.
The automatic objects are alive within the block and they aren't alive outside the block. The objects are destroyed when the block is exited. As such, it is reasonable to say that they are destroyed at the point where the closing brace is.
From ISO standard (Special member functions - Destructors):
Once a destructor is invoked for an object, the object no longer
exists; the behavior is undefined if the destructor is invoked for an
object whose lifetime has ended.
Destructor call is essentially description of actions need to consider object destroyed. Destructor can be called explicitly, it results in end of life for that object. Explicit calls are rare, usually done for objects created by placement new.
Given the example provided, the question is actually about order of destructor calls. The destructors for sub-objects ( base class-type included, if any present) are called after. So you can safely access them until exit from destructor. Order of call is based on declaration order, just like order of initialization but inverted. Subobject of base-class type is considered the first for initialization and the last for destruction.
This question already has answers here:
Automatic destruction of object even after calling destructor explicitly
(5 answers)
Closed 3 years ago.
This code:
#include <iostream>
class Base { };
class Derived : public Base
{
public:
~Derived()
{
std::cout<< "Derived dtor" << std::endl;
}
};
int main()
{
Derived objD;
objD.~Derived();
return 0;
}
prints:
Derived dtor // destructor called
Derived dtor // printed by 'return 0'
I don't have idea from where comes the second line.
With this main:
int main()
{
Derived objD;
return 0;
}
It prints only one line.
What you have here is undefined behavior as per the C++ standard:
As per [class.dtor]/16
Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the destructor is invoked for an object whose lifetime has ended (6.8). [ Example: If the destructor for an automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily invoke implicit destruction of the object, the behavior is undefined. —end example ]
You explicitly call the destructor for the automatic object objD with this statement:
objD.~Derived();
And the implicit destruction of the object is invoked at the end of its scope the closing }.
You create an object on the stack. This object has automatic lifetime managed by its surrounding scope. If you manually invoke the destructor, you do what the compiler does for you, and you end up with undefined behavior.
you call the destructor, c++ have an automated call for destructor after the main function, or after the object is not in used and then the destructor call. you do double "free"
Object destructors are always called when the object goes out of scope. That's a fundamental part of how C++ is designed, enabling memory-safe exceptions, RAII, etc. Manually calling the destructor first has no bearing on that, so if you call it yourself it will (most likely, this is UB) run twice as you can see.
Calling a destructor manually is almost always incorrect and will result in Undefined Behaviour. The one case where it's allowed is when you've created an object in separately-allocated memory via "placement new".
cppreference says about std::atexit :
The functions may be called concurrently with the destruction of the objects with static storage duration and with each other, maintaining the guarantee that if registration of A was sequenced-before the registration of B, then the call to B is sequenced-before the call to A, same applies to the sequencing between static object constructors and calls to atexit
I understand that passage to mean that, if std::atexit is called during static initialization, the registered function will be called during the destruction of static objects just before the destruction of the static object which was last initialized when the std::atexit that registered the function was called. I also interpret "may be called concurrently" to mean the calls can occur between static object destructions as opposed to the multi-threaded interpretation of the word.
What I'm wondering is whether a object is considered as initialized (in the context of this ordering) when it's initialization begins or when it completes. I wrote a short test to test this :
#include <cstdlib>
#include <iostream>
struct foo
{
foo()
{
std::cout << "ctor\n";
std::atexit([]() { std::cout << "atexit\n"; });
}
~foo()
{
std::cout << "dtor\n";
}
};
foo my_foo;
int main()
{
return 0;
}
The output I get is (http://cpp.sh/3bllu) :
ctor
dtor
atexit
This leads me to believe that my_foo is not considered to be initialized in this context until it's construction finishes. In other words, the function is considered to have been registered before my_foo was initialized so the registered function executes after my_foo's destruction.
I can't seem to find anything that would guarantee this behavior and I'm not even entirely sure my initial interpretation of the cited passage is correct. Is the behavior I've described something that I can rely on or is it implementation defined or even undefined behavior?
The call to the destructor will happen before the call to the function passed to atexit. From [basic.start.term], p5:
If a call to std::atexit strongly happens before the completion of
the initialization of an object with static storage duration, the call to the destructor for the object is sequenced
before the call to the function passed to std::atexit.
How should I work with exceptions throwed from constructors of local static objects? For example I have following code:
class A
{
public:
A() {throw runtime_error("Ooops");}
};
void foo()
{
static A a = A();
cout << "Continue" << endl;
}
int main(void)
{
try
{
foo();
}
catch(...)
{
}
foo(); // Prints continue
return 0;
}
As I understand, in the case of second calling foo method, object a is treated as fully constructed object, and constructor is not called. (More over, it seems like destructor of a due first exception throwing is not called)
If that's true, then that is a compiler bug.
(However, VTT claims that this code produces the expected result with Visual Studio 2015, so I recommend double-checking your results.)
Here's the standard-mandated behaviour:
[C++14: 6.7/4]: The zero-initialization (8.5) of all block-scope variables with static storage duration (3.7.1) or thread storage duration (3.7.2) is performed before any other initialization takes place. Constant initialization (3.6.2) of a block-scope entity with static storage duration, if applicable, is performed before its block is first entered. An implementation is permitted to perform early initialization of other block-scope variables with static or
thread storage duration under the same conditions that an implementation is permitted to statically initialize a variable with static or thread storage duration in namespace scope (3.6.2). Otherwise such a variable is initialized the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration. If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization. If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined. [..]
GCC 6.3.0 correctly attempts to reconstruct the A (and thus throws again).
More over, it seems like destructor of a due first exception throwing is not called
No, it won't be. You can't destroy an object that was never successfully created in the first place.
[C++14: 15.2/2]: An object of any storage duration whose initialization or destruction is terminated by an exception will have destructors executed for all of its fully constructed subobjects (excluding the variant members of a union-like class), that is, for subobjects for which the principal constructor (12.6.2) has completed execution and the destructor has not yet begun execution. Similarly, if the non-delegating constructor for an object has completed execution and a delegating constructor for that object exits with an exception, the object’s destructor will be invoked. If the object was allocated in a new-expression, the matching deallocation function (3.7.4.2, 5.3.4, 12.5), if any, is called to free the storage occupied by the object.
By the way, this doesn't fix the problem, but you should just write:
static A a;
The copy-initialisation from a temporary is pointless.
Each instance of static local variable also implicitly creates a global Boolean variable that will be set to true after static variable is constructed. If constructor throws than the next time method is called there will be another attempt to construct a static variable.
The following program :
#include <iostream>
using namespace std;
class Test
{
public:
Test() { cout << "Constructor is executed\n"; }
~Test() { cout << "Destructor is executed\n"; }
};
int main()
{
Test(); // Explicit call to constructor
Test t; // local object
t.~Test(); // Explicit call to destructor
return 0;
}
prints the following output:
Constructor is executed
Destructor is executed
Constructor is executed
Destructor is executed
Destructor is executed
My question is even after explicitly calling destructor in main(), why does the compiler call the destructor implicitly before exiting main()?
As a side question, apart from use in delete operator is there any other use of the strategy of calling destructor explicitly?
You've introduced undefined behavior.
Per the standard:
§ 12.4 Destructors
(11) A destructor is invoked implicitly
(11.3) — for a constructed object with automatic storage duration (3.7.3) when the block in which an object is
created exits (6.7),
and
15 Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the
destructor is invoked for an object whose lifetime has ended (3.8). [ Example: if the destructor for an
automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily
invoke implicit destruction of the object, the behavior is undefined. —end example ]
You explicitly call the destructor or by calling t.~Test(), it is then implicitly invoked when the object leaves scope. This is undefined.
The standard provides this note as well:
14 [ Note: explicit calls of destructors are rarely needed. One use of such calls is for objects placed at specific
addresses using a placement new-expression. Such use of explicit placement and destruction of objects can
be necessary to cope with dedicated hardware resources and for writing memory management facilities.
This is not an "explicit call to constructor":
Test(); // Explicit call to constructor
It constructs a temporary object, which implicitly calls the constructor, then the temporary immediately goes out of scope, which implicitly calls the destructor. You can't explicitly call a constructor, it gets called implicitly when you construct an object.
My question is even after explicitly calling destructor in main(), why does the compiler call the destructor implicitly before exiting main()?
Because the compiler always destroys local variables. Just because you did something dumb (manually destroyed an object that gets destroyed automatically) doesn't change that.
As a side question, apart from use in delete operator is there any other use of the strategy of calling destructor explicitly?
It's used when managing the lifetime of objects in raw memory, which is done by containers like std::vector and other utilities like std::optional.
My question is even after explicitly calling destructor in main(), why does the compiler call the destructor implicitly before exiting main()?
The destructor will be called when the object gets out of scope, regardless of whether you call the destructor explicitly or not. Don't explicitly call the destructor for objects with automatic storage duration.
As a side question, apart from use in delete operator is there any other use of the strategy of calling destructor explicitly?
Yes. When you initialize an object using the placement new expression, you need to call the destructor explicitly. Sample code from the above site:
char* ptr = new char[sizeof(T)]; // allocate memory
T* tptr = new(ptr) T; // construct in allocated storage ("place")
tptr->~T(); // destruct
delete[] ptr; // deallocate memory
the scope of t is the main function. Its created on the stack and will be destroyed at the end of the function.
That's how its supposed to work and when you call the destructor on it early, you don't change that.
You don't need to call the destructor and in this case doing so leads to it being called twice.
if you'd used
Test* t = new Test();
the destructor would not have been automatically called at the end of main.
The compiler does not care if you called the destructor explicitly or not. The local object t gets out of scope, that's why it gets destroyed and the destructor is called.
It is no good practice to call destructors explicitly. Instead you should write a method like cleanup() that can be called explicitly as well as from within the destructor. If you want to avoid that cleanup can be called twice, add something like this to you class:
private:
bool cleanupPerformed;
void cleanup()
{
if( !cleanupPerformed )
{
// ... do cleanup work here ...
cleanupPerformed = true;
}
}