Is object can be destroyed when called the destructor explicitly? - c++

Have a look at following code:
#include <iostream>
#include <memory>
class A
{
public:
A()
{
std::cout << "A() \n";
}
~A()
{
std::cout << "~A() \n";
}
int a = 100;
};
class B
{
public:
B()
{
ptr.reset(new A());
std::cout << "B() \n";
std::cout << "pointer value" << ptr.get() << std::endl;
std::cout << ptr->a << std::endl;
}
~B()
{
std::cout << "~B() \n";
}
void print()
{
std::cout << "print() " << a << b << "\n";
std::cout << "pointer value" << ptr.get() << std::endl;
std::cout << ptr->a << std::endl;
}
private:
std::unique_ptr<A> ptr;
int a = 10;
int b = 5;
};
int main()
{
std::unique_ptr<B> p1(new B());
p1->~B();
p1->print();
return 0;
}
the output result:
A()
B()
pointer value010ECB60
100
~B()
~A()
print() 105
pointer value010ECB60
-572662307
~B()
~A()
The Question is:
When class B's destructor called, class A's destructor also called, and class A's member a = 100 has been destroyed, but class B's member a = 10; b = 5 still exist, and it's value not changed, so class B's destructor can't be seen as a function, since it called class A's destructor, how to explain this?
When exit the main() function, the destructor of class B called second time automatically, and code breaks with the error code HEAP[Destructor.exe]: Invalid address specified to RtlValidateHeap( 00EA0000, 00EACE38 ), because class B's destructor called first time so object A has been destroyed, this will destroy it twice?
I add some print info to track workflow, but i still don't figure out how it worked when called the destructor explicitly.

When class B's destructor called, class A's destructor also called, and class A's member a = 100 has been destroyed, but class B's member a = 10; b = 5 still exist, and it's value not changed, so class B's destructor can't be seen as a function, since it called class A's destructor, how to explain this?
No, they do not exist, both B and A objects have been destroyed, it is just that dereferencing a dangling pointer (p1.get() during p1->print()) is undefined behaviour. In this case, the compiler just did not bother with clearing the memory locations used for the storage of the object B.
When exit the main() function, the destructor of class B called second time automatically, and code breaks with the error code HEAP[Destructor.exe]: Invalid address specified to RtlValidateHeap( 00EA0000, 00EACE38 ), because class B's destructor called first time so object A has been destroyed, this will destroy it twice?
Well, you destroyed the object held by p1 but in a way p1 was not aware it has been destroyed. Then when ~unique_ptr has been called on p1, it tried to destroy already destroyed object. Instead, you should just use p1.reset() which will call ~B and update p1's state accordingly to prevent the mentioned issue.

To really understand what is going on here, you need to understand there are really two related processes that happen when recycling an object's memory. There's destruction (which is calling the class destructor to clean up any other objects the object refers to), and there's deallocation (which makes the memory available for reuse). Normally for objects on the heap, one calls delete which does both of these things. For std::unique_ptr, its destructor call its deleter, which by default calls delete on the object the unique_ptr points at.
When you call a destructor explicitly (with p1->~B() in your case), it destroys the object but does not deallocate it. That leaves the object in a "broken" state where you can't do anything with it (not even call delete safely), but where it hasn't been deallocated either, so all you can do is kill any references to it (with .release()) and let the memory leak. So you should never call the destructor explicitly.
If you try to access an object after it has been destroyed, you get undefined behavior, but if you try it before the object has been deallocated (as you are doing in your example), you'll probably just see the same data, as the memory has not yet been overwritten by anything else.

Usually you don't need to call destructor explicitly. For automatic objects and dynamically allocated objects (using new/delete) lifetime of object coincides with liftime of its storage, and constructors and destructors called automatically. But sometimes storage is allocated separatelly and in this case constructor(well, sort of) and destructor should be called explicitly. Here is example code from: https://en.cppreference.com/w/cpp/language/new
{
// Statically allocate the storage with automatic storage duration
// which is large enough for any object of type `T`.
alignas(T) unsigned char buf[sizeof(T)];
 
T* tptr = new(buf) T; // Construct a `T` object, placing it directly into your
// pre-allocated storage at memory address `buf`.
 
tptr->~T(); // You must **manually** call the object's destructor
// if its side effects is depended by the program.
} // Leaving this block scope automatically deallocates `buf`.
Same techniques used in different containers, for example std::vector.

Related

Class and member destructors called twice

class A
{
public:
~A()
{
std::cout << "A destroyed" << std::endl;
}
};
class B
{
public:
A a;
~B()
{
std::cout << "B destroyed" << std::endl;
}
};
int main()
{
B b;
b.~B();
}
Output:
B destroyed
A destroyed
B destroyed
A destroyed
Can someone explain to me what's going on here? I expected the output to be
B destroyed
A destroyed
(once when ~B() is called and once ~A() is called).
Any object that was created in a limited scope would be destroyed when the scope is exited.
Meaning, that if you have created an object on the stack, it will be destroyed when the stack will fold back, along with any other variables declared in that scope.
The only exception to this is when you are using dynamic allocation of objects, using the keyword new, this creates the object on the heap, which doesn't clean itself on its own. But even then, calling delete will invoke the destructor on its own.
Having said that, in order to avoid using new and delete, and for better resource management, there are types (such as smart-pointers) that handle these on their own, in a technique called Resource Allocation Is Initialization (or RAII), which makes things much simpler (and you get to the first part, all is allocated on the stack, thus the destructors are being called automatically when it folds).

C++ destructor order of member with shared_ptr

If class A contains class B, then when A destruct, B's destructor will be called first, i.e., the reversed order of their nested relationship.
But what if A contains a shared_ptr of B, while B contains a raw pointer to A, how should we handle the destructor to make it safe?
Considering the following example:
#include <iostream>
#include <memory>
#include <unistd.h>
struct B;
struct A {
int i = 1;
std::shared_ptr<B> b;
A() : b(std::make_shared<B>(this)) {}
~A() {
b = nullptr;
std::cout << "A destruct done" << std::endl;
}
};
struct B {
A *a;
B(A *aa) : a(aa) {}
~B() {
usleep(2000000);
std::cout << "value in A: " << a->i << std::endl;
std::cout << "B destruct done" << std::endl;
}
};
int main() {
std::cout << "Hello, World!" << std::endl;
{
A a;
}
std::cout << "done\n";
return 0;
}
You can see in A's destructor, I explicitly set b to nullptr, which will trigger B's destructor immediately, and blocking until it finish.
The output will be:
Hello, World!
value in A: 1
B destruct done
A destruct done
done
but if I comment out that line
~A() {
// b = nullptr; // <---
std::cout << "A destruct done" << std::endl;
}
The output will be:
Hello, World!
A destruct done
value in A: 1
B destruct done
done
it seems that A's destructor finished without waiting B to destruct. But in this case, I expected segment fault, since when A already destructed, B tried to access the member of A, which is invalid. But why the program doesn't produce segment fault? Does it happen to be OK (i.e., undefined behavior)?
Also, when I change
{
A a;
}
to
A * a = new A();
delete a;
the output is still the same, no segment fault.
It is important to be precise about what is happening. When A is destroyed, the following events happen in the following order:
A::~A() is called.
The A object's lifetime ends. The object still exists, but is no longer within its lifetime. ([basic.life]/1.3)
The body of A::~A() is executed.
A::~A() implicitly calls the destructors of direct non-static members of A in reverse declaration order ([class.dtor]/9, [class.base.init]/13.3)
A::~A() returns.
The A object ceases to exist ([class.dtor]/16). The memory that it used to occupy becomes "allocated storage" ([basic.life]/6) until it is deallocated.
(All references are to the C++17 standard).
In the second version of the destructor:
~A() {
std::cout << "A destruct done" << std::endl;
}
after the statement is printed, the member b is destroyed, which causes the owned B object to be destroyed. At that point, i has not yet been destroyed, so it is safe to access it. After that, the B destructor returns. Then, i is "destroyed" (see CWG 2256 for some subtleties). Finally, the destructor of A returns. At that point, it would no longer be legal to attempt to access the member i.
B has a pointer to A, but doesn't deallocate the memory of it (e.g. no delete). So The pointer is removed but not the memory allocated, which is all fine.
Basically, the pointer is on the stack and it contains the address of some (assumed) allocated memory on the heap. Yes it get removed from the stack, but the allocated memory remains. That's what delete is for. To remove the allocated memory on the heap. However in your case, you don't want that memory to be removed and your pointer is what we call a non-owning pointer. It points to something, but it's not responsible about the cleanup (actually B doesn't own the memory that the pointer is pointing to).
Just wanted to point out that your comment is incorrect:
~A() {
std::cout << "A destruct done" << std::endl;
}
A destructor is DONE when you get out of the curly braces. You can see that in a debugger, doing step-by-step. That is where b will be deleted.
If class A contains class B, then when A destruct, B's destructor will be called first, i.e., the reversed order of their nested relationship.
No. If you destroy an object of type A, that calls the destructor of A, so that is called first.
However, call to B's destructor will finish first: The destructor of A begins by executing the destructor body, and then proceeds to destroy the sub objects. The destructor body finishes first, then the sub object destructors, and finally the destructor of A will be complete.
But what if A contains a shared_ptr of B, while B contains a raw pointer to A, how should we handle the destructor to make it safe?
In the destructor body of A, make the pointed B point somewhere else other than the object that is being destroyed:
~A() {
b->a = nullptr;
}
If you point it to null such as in my shown example, then you must also make sure that B can handle the situation that B::a may be null i.e. check before accessing through the pointer.
it seems that A's destructor finished without waiting B to destruct.
That's not what we observe. The body of the destructor of A has finished, but the destructor does not finish until the member destructors finish first.

Why is there a memory leak when an exception is thrown from a constructor?

I read the book C++ How to Program 8th Edition by Paul Deitel. There is a statement at p.645:
When an exception is thrown from the constructor for an object that's created in a new expression, the dynamically allocated memory for that object is released.
To verify this statement, I wrote code as follows:
#include <iostream>
#include <exception>
#include <memory>
class A{
public:
A(){std::cout << "A is coming." << std::endl;}
~A(){std::cout << "A is leaving." << std::endl;}
};
class B
{
public:
B()
{
std::cout << "B is coming." << std::endl;
A b;
throw 3;
}
~B(){std::cout << "B is leaving." << std::endl;}
};
int main(void)
{
try
{
std::shared_ptr<B> pi(new B);
}
catch(...)
{
std::cout << "Exception handled!" << std::endl;
}
}
The output is:
B is coming.
A is coming.
A is leaving.
Exception handled!
This shows that B's destructor isn't invoked, which seems to conflict with the statement above.
Is my code correct to verify the statement? If not, how should I modify it? If yes, does it mean that the statement is wrong?
You're confusing two things:
memory being released
the destructor being called
You've shown that the latter doesn't occur, which makes sense: how can you destroy something that wasn't properly constructed? Note that the member variables will have their destructors invoked, though, because by the time the constructor threw an exception all the member variables had been fully constructed.
But that has nothing to do with memory being released, which will assuredly occur.
[C++11: 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.
It means that everything in the ctor of B up to the point of the exception is destruction. An instance of B itself was never constructed, therefore it must not be destructed. Note also that pi was never constructed.
std::shared_ptr<B> pi(new B) - start with new B
new B - triggers the ctor of B
std::cout ... - the output
A b; - construct an A
throw 3; - calls ~A()
- rewind, new B is "aborted"
- std::shared_ptr<B> pi(new B) is "aborted"
You could modify your code to see, that the constructor of the std::shared_ptr is never hit by replacing it with a new class of yours, taking a pointer:
struct T {
T(B*) { std::cout << "T::T()\n"; }
};
...
try
{
T pi(new B); // instead of std::shared_ptr<B> pi(new B);
}
...
The constructor of T will not be hit (cf. "pi was never constructed").
Now assume that the constructor of B would allocate memory as in:
B()
{
A* a = new A(); // in contrast to A a;
throw 3;
}
were previously A::~A() was called, that is a was deconstructed, we now have a pointer, and pointers don't need to be deconstructed. However the memory allocated and assigned to a is not deleted. (Had you used a smart pointer std::unique_ptr<A> a = std::make_unique<A>();, the memory would have been released, because the destructor of std::unique_ptr<A> is called and it will release the memory.)

c++ destroy an object on stack frame

I try to understand what happen when an object destroy on stack.
here is my sample code:
#include <stdio.h>
struct B {
~B() {puts("BBBB");}
};
int main()
{
B b;
b.~B();
}
output is
BBBB
BBBB
based on the output, I can tell the object is destroy twice.one is ~B(), another one is after "}". how and why can a object get destroy twice?
update:
after i review replies, I think the destructor doesnt destroy this object. it there a way to destroy an object before it reach out of scope "}".
Thanks
You are not supposed to invoke the destructor by hand. What's happening is you are invoking the destructor and then when the object gets popped off the stack the destructor is called again automatically by the compiler.
~B() is called before the destruction
Destructors are usually used to deallocate memory and do other cleanup
for a class object and its class members when the object is destroyed.
A destructor is called for a class object when that object passes out
of scope or is explicitly deleted.
Source
So you are just calling a function twice.
There's minimal-to-no garbage collection in C++, objects are simply destroyed when they go out of scope. So you could replace your test to this:
#include <iostream>
struct B {
B() { std::cout << "B()" << std::endl; }
~B() { std::cout << "~B()" << std::endl; }
};
int main()
{
std::cout << "start main" << std::endl;
{ // scope
std::cout << "start scope" << std::endl;
B b;
std::cout << "end scope" << std::endl;
} // <-- b gets destroyed here.
std::cout << "end main" << std::endl;
}
If you want an object on the stack over which you have control over the lifetime of, you can do something like this:
#include <iostream>
#include <memory.h>
struct B {
B() { std::cout << "B()" << std::endl; }
~B() { std::cout << "~B()" << std::endl; }
};
int main()
{
std::cout << "start main" << std::endl;
{ // scope
std::cout << "start scope" << std::endl;
void* stackStorage = alloca(sizeof(B));
std::cout << "alloca'd" << std::endl;
// use "in-place new" to construct an instance of B
// at the address pointed to by stackStorage.
B* b = new (stackStorage) B();
std::cout << "ctord" << std::endl;
b->~B(); // <-- we're responsible for dtoring this object.
std::cout << "end scope" << std::endl;
} // <-- b gets destroyed here, but it's just a pointer.
std::cout << "end main" << std::endl;
}
Live demo: http://ideone.com/ziNjkd
Remember, though, it's the stack. When it goes out of scope, it goes away - if you don't destroy it, it just dissapears.
{
void* stackStorage = alloca(sizeof(B));
B* b = new (stackStorage) B(); // "in-place new"
} // (*b)s memory is released but (*b) was not dtord.
The only time you would manually call a destructor is when you've got grounds to use placement new
Keep in mind that the destructor is like any other function. The only difference with other function is that it is automatically called when the object is deallocated. You cann see this like an event. You get a chance to clean everything before the object get annihilated. Calling the destructor by hand does not deallocate the object.
Object construction/destruction in C++ follows this simple rule:
Anything automatically allocated (and constructed) is automatically destructed.
Anything explicitely allocated with new is explicitely destructed via delete.
Anything explicitely constructed with new() must be explicitely destructed by calling the destructor.
The destructor has to be called in all three cases, the difference is in how the memory for the object is allocated:
The object is on the stack, its allocation is managed by the compiler.
The object is on the heap, its allocation is managed by the programmer.
The object is anywhere, construction and destruction is independent of allocation.
In the first two cases, we have a combination of allocation and construction, and consequently a combination of destruction and deallocation. The third case is entirely different, but fully supported by the language, and the reason that you are allowed to explicitely call a destructor; because in this case an object is constructed without allocating memory for it. Consequently, it must be destructible without deallocating memory as well. This case can be used like this:
void* buffer = (void*)new char[sizeof(Foo)]; //allocation
Foo* myFoo = new(buffer) Foo(); //construction
myFoo->~Foo(); //destruction
Foo* anotherFoo = new(buffer) Foo(); //reuse the buffer to construct another object in it
anotherFoo->~Foo(); //destruction of the second object
delete buffer; //deallocation
Note, that this actually constructs two objects, one after the other in the same place, destructing them explicitely before the memory is reused. The buffer could also be a large slap of memory to store many objects, std::vector<> works like this.
So, yes, destruction does destroy your object, you must not use it after destruction. But since you used an automatically allocated and constructed object in your question, the compiler also took care of destructing it, leading to the double destruction. This is always a bug, objects must never be destructed twice, but the language allows you to do it anyway.
What you are doing is a pretty good example of a variable running out of scope.
int main()
{
//Main is started
B b;
/* What happens is that `b` is constructed as a local
variable and put on the runtime stack.*/
b.~B();
/*You then invoke the destructor manually which is bad practice.
But it is possible and it will execute the code.
However, the state of the resulting instance is undefined.*/
}
/*Main ends and local variables defined in the
current scope get destroyed. Which also means that B's destructor
is called the second time */
FYI - the only time you are supposed to do manual destruction of an object is when it is put on the heap like this:
// create an instance of B on the heap
B* b = new B();
// remove instance and implicitly call b's destructor.
delete b;
i would like to answer my own question.
after a lot of reading, Here is my summary.
1. destructor doesnt destroy it's object. the object stays at stack
until out of scope.
2. nothing can destroy a stack object.
3. the destructor did destroy RESOURCE inside the object.
sample code:
struct B {
B() {happy="today is a good day"; hour = 7;}
~B() {puts("BBBB");}
std::string happy;
int hour;
};
int main()
{
B b;
std::cout << b.happy << b.hour <<std::endl;
b.~B();
std::cout << b.happy << b.hour <<std::endl;
}
output:
today is a good day7
BBBB
7
BBBB
we can see a resource b.happy is gone after b.~B() is called. this is a proof of my point 3.
you see the b.hour(int type is not a resource) is still here. this is a proof of my point 1.

Confused about C++ memory deallocation

So in C++ if I create an object useing new I should always deallocate it using delete
For example
Segment::Segment(float length)
{
segmentLength = length;
angle = 0.0f;
x = Rand::randFloat(1.0f, 1.5f);
y = Rand::randFloat(1.0f, 1.5f);
vx = Rand::randFloat(0.0f, 1.0f);
vy = Rand::randFloat(0.0f, 1.0f);
prevX = Rand::randFloat(0.0f, 1.0f);
prevX = Rand::randFloat(0.0f, 1.0f);
};
And lets say I use it like this in another class such as,
this._segmentObject = Segment(2.0f);
this._segmentPointer = new Segment(2.0f);
In the destructor of that class, I know I should call delete on the this._segmentPointer, however how do I make sure memory is deallocated for the other one?
however how do I make sure memory is deallocated for the other one?
It is automatically. This is why this type of storage is called automatic. Automatic storage is released at the end of the storage’s life cycle, and the objects’ destructors called.
The object life-cycle ends when the program control leaves the scope where the object has been allocated.
Things not allocated with new, new[] or the malloc family should be destructed and "freed" when the object goes out of scope.
Often this simply means that that the code has reached the end of the block it was declared it or that the object that it was in was destructed (one way or another).
To see this in action, you can do something like this:
struct C {
C() { std::cout << "C()" << std::endl; }
~C() { std::cout << "~C()" << std::endl; }
};
struct B {
B() { std::cout << "B()" << std::endl; }
~B() { std::cout << "~B()" << std::endl; }
private:
C c_;
};
struct A {
A() { std::cout << "A()" << std::endl; }
~A() { std::cout << "~A()" << std::endl; }
};
int main() {
B *b = new B; // prints "B()", also constructs the member c_ printing "C()"
{ // starts a new block
A a; // prints "A()";
} // end of block and a's scope, prints "~A()"
delete b; // prints "~B()", also destructs member c_, printing "~C()"
}
Note: that if we did not do delete b, the "~B()" and "~C()" would never print. Likewise, if c_ were a pointer allocated with new, it would need to be delete'd in order to print "~C()"
The memory for this._segmentObject is part of the memory of the containing object, and will be released when the containing object is destroyed.
this._segmentObject is assigned from a temporary object that is created on the stack and deleted when it goes out of scope.
Not only that, You should only allocate with new and deallocate with delete in Constructors or Destructors, otherwise your program can leak if an exception is thrown.
The destructors for all class-type member objects are called at the time of the destruction of the primary class. So your this object, which is allocated on the stack, will have it's destructor called when it goes out-of-scope. At that time, any class-type member objects of your this object will have their own destructors called in addition to the destructor for your this object which will call delete on the member pointer.
For instance, take the following code sample:
#include <iostream>
using namespace std;
class A
{
public:
A() {}
~A() { cout << "Destructor for class A called" << endl; }
};
class B
{
private:
A a;
public:
B() {}
~B() { cout << "Destructor for class B called" << endl; }
};
int main()
{
B b;
return 0;
}
When run, the output becomes the following:
Destructor for class B called
Destructor for class A called
So you can see that when b, which is allocated on the stack, goes out-of-scope at the end of main, the destrutor for class B is called, which in-turn, after executing the body of the destructor function, calls the destructors for any of its class-type member data objects, which in this case would mean the destructor for class A. Therefore in your case, the pointer would have delete called on it in the destructor for your this class, and then the destructor for _segmentObject would be called after the destructor for this had completed execution of the body of its destructor. Then once all the destructors for the non-static data-member objects had been called, the destructor for this then returns.
The _segmentObject is allocated automatically on the stack.
The object destructor will be called automatically when the variable gets out of scope.
As others have said, you don't need to explicitly do anything to reclaim the memory used by this._segmentObject. As soon as it goes out of scope, the memory will be reclaimed.
It's not clear why you would use Segment in both ways. You should try to ensure you use the Resource Acquisition Is Initialization idiom, as it removes much of the need for checking new / delete pairs. That is, just use the this._segmentObject version, not the pointer.
Your application may not allow it, though.