When is C++ destructor called on an object in heap? - c++

Suppose a class and its usage
#include <vector>
class B
{
public:
B() {temp = 0;}; // implemented
~B() {} ; // implmented
private :
int temp;
// it holds a std::bitset , a std::vector.. It is quite large in size.
};
class A
{
private:
std::vector<B*> * _data ;
public:
A()
{
_data = new std::vector<B*>(0);
}
~A()
{
for(unsigned int idx_ = 0; idx_ < _data->size(); ++idx_)
delete _data->at(idx_);
delete _data ;
}
void addB()
{
B * temp = new B();
_data->push_back(temp);
}
}
int main()
{
A temp;
temp.addB();
// Do something
}
My question is does this code leak memory ? Also suppose another usage
int main()
{
A * temp = new A();
temp->addB();
delete temp ; // 1
}
Is 1 here required ? If I have a pointer to the heap and the pointer goes out of scope is the destructor called on the element in heap. I just want to be sure about this point.
Thank you !

To make it easier to associate when a destructor will be called and when it wont be, use this rule of thumb: When the memory for an object is being reclaimed, then the object's destructor is called (and the memory is reclaimed right after that).
Your first example does not leak any memory.
Here is why... You essentially created 2 objects.
A and B.
A was on the stack. The memory for object A was created implicitly on the stack.
B was created on the heap explicitly by your code.
When main() returned every Object on the stack is destroyed. i.e the memory that was being used to hold the members of the object on the stack (in this case object A) is being reclaimed implicitly. Since the object (A) is actually being destroyed and its memory being reclaimed, the destructor for A gets called.
Within A's destructor you are explicitly telling the runtime to reclaim all the memory what was explicitly allocated by your code (i.e when you call delete). Thus the memory for object B is being reclaimed too.
Thus there was no leak.
In the 2nd example, you again create 2 objects A and B.
Here, the memory for both objects resides in the heap. This was allocated explicitly by your code using the new operator.
In this case, your code never reclaims the memory allocated for A. i.e delete is never called for A.
The stack for main() only contains the memory for a pointer to A. The main() stack itself does not contain the memory for A. So when main() returns, all that is being destroyed is the memory that was allocated for the pointer to A, and not A itself.
Since the memory for A was never reclaimed, it was never "destroyed". Thus its destructor was never called and correspondingly "B" was never destroyed either.

No, destructor is not implicitly called. you have to delete temp, at which time it's destructor is called. It could be argued that since it's main that's returning in your example, the process is going to exit and memory will be reclaimed by OS, but in general, each new needs a delete.

The rule of thumb is if you've used new to create something then you have to use delete to destroy it. Pointers are all about manual memory management (they are heritage from the C language) or, as Scott Meyers once called them, "running with scissors". References are a C++ thing (or you can also check out smart pointers like std::shared_ptr).
UPDATE
I thought it would be useful to show an example with std::shared_ptr. It has dumb pointer semantics, but its destructor -since it actually has one- calls pointed object's destructor.
#include <memory>
#include <iostream>
#include <string>
#include <type_traits>
using namespace std;
struct Simple {
std::string txt;
Simple(const std::string& str) : txt(str) {}
Simple(){}
~Simple() { cout << "Destroyed " << txt << endl; }
};
template<class U> using SPtr = shared_ptr<U>;
template<class V> using PtrToSimple = typename conditional<is_same<SPtr<Simple>, V>::value,SPtr<Simple>,Simple*>::type;
template<class T>
void modify(PtrToSimple<T> pt) {
pt->txt.append("_modified");
// equivalent to (*pt).txt.append("_modified");
}
int main() {
auto shared = shared_ptr<Simple>(new Simple("shared_ptr_obj"));
modify<decltype(shared)>(shared);
cout << shared->txt << endl;
auto dumb = new Simple("dumb_ptr_obj");
modify<decltype(dumb)>(dumb);
cout << dumb->txt << endl;
// The object pointed by 'shared'
// will be automatically deleted.
// dumb's object won't
return 0;
}
prints
shared_ptr_obj_modified
dumb_ptr_obj_modified
Destroyed shared_ptr_obj_modified

Related

Is object can be destroyed when called the destructor explicitly?

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.

Destructor to call free() to free dynamically allocated memory using malloc

In C++, if I have some dynamically allocated memory using malloc, can I free the same by calling free() from destructor and then explicitly call the destructor via class object?
Trying to do that but getting an exception.
Is it now allowed?
So here I'm explicitly calling the destructor. Is this allowed? I mean, I'm calling it to free memory. I did read that after the scope, the destructor is called implicitly. Does this mean the free() will try to happen twice?
My code snippet:
class School
{
int a;
};
class Test
{
public:
School* school;
void Run()
{
school = (School*)malloc(sizeof(School));
}
~Test()
{
if (NULL != school)
{
free(school);
school = NULL;
}
}
};
int main()
{
Test t;
t.Run();
t.~Test();
return 0;
}
Your code destroys t twice. It is destroyed first when you call the destructor and then again when it goes out of scope. You cannot create one object and then destroy two objects.
You can explicitly call the destructor, and that has sense whenever you create the object using an placement new.
You may get an exception if you have the opposite order of operations. First you need to call the destructor, as it needs to free all the resources that the object may have allocated. You need to call the free function only after all resources of the object are deallocated/destroyed. For example:
struct S {
~S() {
delete ptr;
}
int *ptr;
};
int main() {
char *buf = (char*) malloc(sizeof(S)) ;
S *s = new (buf)S();
// Do not call free here as the destructor needs to access the s.ptr:
//free(buf);
s->~S();
free(buf);
return 0;
}

Is the heap-allocated object of a class alive after its scope but before calling its destructor in C++

EDITED: Let's say we don't call explicitely the destructor of a heap-based object (delete A). If the pointer that points to "A" goes out-of-scope, is there a way the dynamic object remain accessible? for e.g., in the following code, can "a" be still alive after if-closing }?
class A{
void itsmethod();
};
int main()
{
if (true){
A* a = new A;
}
//...here how can I use dynamically allocated object?
a->itsmethod();
}
EDIT: As it was responded, the simplest immediate way is defining the pointer outside of if statement, but I am just wondering if there is any other option to prolong lifetime of dynamic object? Accordingly what else "A" class should provide? For instance passing by reference? Or equipping the class with move constructor... These suggestions may be irrelevant, I would like to hear your feedback.
I wonder if the object "a" is still alive after if-closing }?
The object a, which is a pointer, is not alive after the closing } of the if statement. The object to which a points to is in memory but it is not accessible with the posted code.
To be able to access the object to which a points to, declare a before the if statement.
int main()
{
A* a = nullptr;
if (true)
{
a = new A;
}
if ( a != nullptr )
{
a->itsmethod();
}
}
No and Yes: yes because dynamic memory is not freed up automatically. No because the code doesn't compile because a is scoped to if block and you are trying to use it from outside.
class A{
public:
int x;
};
int main(){
A* ptrA = NULL;
if(true){
// Everything declared here is accessible only here whatever being dynamic or static.
ptrA = new A;
ptrA->x = 10;
int x;
}
if(ptrA){
std::cout << ptrA->x << std::endl; // 10
delete ptrA;
}
return 0;
}
You must free up memory always when you're done with it otherwise it is a memory leak.
Above x is declared inside the if block on the stack so when end of if block is reached x will be destructed.
The object created by the new expression (i.e. by new A) will continue to exist.
The pointer a itself, since it has passed out of scope, will cease to exist as far as your program is concerned.
The net effect is that the dynamically allocated object is "leaked". It continues to exist after the block but there is no pointer or reference to it.
If you do something like
int main()
{
A *b;
if (true)
{
A* a = new A;
b = a;
}
a->itsmethod(); // diagnosible error
b->itsmethod(); // will work correctly
delete b; // destroy dynamically allocated object
b->itsmethod(); // undefined behaviour
}
then a->itsmethod() will give a compiler diagnostic (since a no longer exists) but the first b->itsmethod() will use the object created by the new expression. The second b->itsmethod() will compile, but yield undefined behaviour, since it accesses an object that no longer exists (due to the preceding delete b).
This happens because the pointer b continues to exist and, within the enclosed block, is assigned the value from a. So it then contains the result of the new expression.
No. The object 'a' will not be accessible anymore since its scope belongs to the if statement. However, there still is a memory address containing that object. This is why its good to do 'garbage collection' in programming.
Let's consider this demonstrative program
#include <iostream>
struct A
{
const char *s;
std::ostream & operator ()( std::ostream &os = std::cout ) const
{
return os << s;
}
};
int main()
{
A *a1;
if ( true )
{
A *a2 = new A { "Hello, Sepideha" };
a1 = a2;
}
( *a1 )() << std::endl;
delete a1;
return 0;
}
Its output is
Hello, Sepideha
Here the object a1 that has the type A * has the outer-most block scope of the function main.
The object a2 has the block scope of the if statement. It is alive only within this block.
At the same time there is dynamically created unnamed object of the type A pointer to which is assigned to a2 and then to a1. This unnamed object will be alive until the operator delete for a pointer that points to the object will be called. That is its live-time does not depend on the block scope of the if statement.
Because the pointer a1 points to this unnamed object then the pointer can be used outside the if statement to access the unnamed object in the dynamic memory.
After the statement with the delete operator this unnamed object stops to exist. But the object a1 is still alive.

Does a destructor automatically deallocates heap memory for member variables?

I have a few doubts related to destructor.
class cls
{
char *ch;
public:
cls(const char* _ch)
{
cout<<"\nconstructor called";
ch = new char[strlen(_ch)];
strcpy(ch,_ch);
}
~cls()
{
//will this destructor automatically delete char array ch on heap?
//delete[] ch; including this is throwing heap corruption error
}
void operator delete(void* ptr)
{
cout<<"\noperator delete called";
free(ptr);
}
};
int main()
{
cls* cs = new cls("hello!");
delete(cs);
getchar();
}
Also, as a destructor is automatically called upon delete why do we need an explicit delete when all the logic can be written in destructor?
I am super confused regarding operator delete and destructor and couldn't make out their specific usage. An elaborate description would be very helpful.
EDIT:
My understanding based on the answers:
For this particular case, a default destructor will corrupt the char pointer so we need to explicitly delete the char array first other wise it will result in memory leak. Please correct me if I am wrong.
Well, a default destructor deallocates memory that is used by member variables (i.e. the member pointer ch itself ceases to exist), but it does not automatically deallocate any memory that is referenced by member pointers. So there is a memory leak in your example.
delete is not a function (though you can overload it); and yes, it is good practice that the logic for the deallocation be written in the destructor. But it is incorrect to assume that the deallocation will be automatically performed by the destructor. The thing is that the destructor will be called at the end of the object's lifetime, but what it does it dependent upon the code you write for it. That is, you should call delete[] on ch inside the destructor:
~cls()
{
delete[] ch;
ch = nullptr;
}
Moreover, I believe the heap corruption error is coming from that fact that you did not leave enough room in the initialization of ch for the null byte \0. You should also be using the the member-initializer list. Change your constructor to this:
cls(const char* _ch) : ch(new char[1+strlen(_ch)])
{
std::cout << "\nconstructor called";
std::strcpy(ch, _ch);
}
There are many improvements that can be made to your code. Namely, using std::string and following the Rule Of Three. Your code also doesn't need a operator delete() overload. cs should be stack allocated:
#include <iostream>
#include <string>
class cls
{
std::string ch;
public:
cls() { std::cout << "default constructor called\n"; }
cls(std::string _ch) : ch(_ch)
{
std::cout << "constructor called\n";
}
cls(cls const& other) : ch(other.ch)
{
std::cout << "copy-constructor called\n";
}
~cls() { std::cout << "destructor called\n"; }
};
int main()
{
cls cs("hello!");
std::cin.get();
} // <-- destructor gets called automatically for cs
No, the destructor won't magically delete the memory pointed to by ch for you. If you called new (you did in the constructor) then you must also call delete at some appropriate time.
A destructor executes when an object is being destroyed. This can be when an automatic object (that is something allocated on the stack) is about to go out of scope, or when you explicitly delete an object allocated with new.
Generally, think of new as a way of getting memory allocated, a constructor as a way of taking that memory and making it into an object, a destructor as taking an object and destroying it, leaving behind a chunk of memory and delete as taking that chunk of memory and deallocating it.
As a convenience for you, when you call new the compiler will call the constructor for you after it allocates the memory you requested and when you call delete the compiler will automatically invoke the destructor for you.
You are getting heap corruption errors because you have a buffer oveflow: you are not allocating space for the null terminating byte that strcpy appends.
Remember a C string is a sequence of bytes followed by a null byte. This means that a string of length 5 actually requires 6 bytes to store.
Also remember that you can and should use std::string instead of C style arrays to save yourself the trouble and avoid having to write error-prone code when there's a very robust and full-featured implementation already available for your use.
With the notable exception of homework/learning exercises, there is hardly a situation where you should implement C style strings directly instead of using std::string.
The same (albeit a little less strict) goes for dynamic arrays in general. Use std::vector instead.
There is no use in override the delete Operator for a specific class. That's what the global delete Operator is for.
What you should do is a delete[] on ch in the destructor. This has to be done explicitly, as the delete Operator only deallocates the memory directly allocated to store the class' instance. As you are allocating further Memory in the constructor you have to free it upon destruction.
As a rule of thumb you can assume that con- and destructor need to be coded symmetricly. For every new in the constructor, has to be a delete in de destructor.
Oh and by the way: You must not mix C++ allocators (new/delete) with C allocators (malloc/free). What you allocate in C++, you have to free in C++ and vice versa.
C++ memory magnament is based on RAII. That means that destructors are called when the lifetime of a variable ends.
For example:
class Foo
{
public:
Foo() { cout << "Constructor!!!" << endl; }
~ Foo() { cout << "Destructor!!!" << endl; }
};
int main()
{
Foo my_foo_instance;
}
Prints:
Constructor!!!
Destructor!!!
Because the constructor is called in the initiallization of my_foo_instance (At the declaration), and the destructor is called when the lifetime of my_foo_instanceends (That is, at the end of main() ).
Also, this rules works for any context, including class attributes:
class Foo1
{
public:
Foo1() { cout << "Foo1 constructor!!!" << endl; }
~ Foo1() { cout << "Foo1 destructor!!!" << endl; }
};
class Foo2
{
private:
Foo1 foo1_attribute;
public:
Foo2() { cout << "Foo2 constructor!!!" << endl; }
~ Foo2() { cout << "Foo2 destructor!!!" << endl; }
};
int main()
{
Foo2 my_foo2_instance;
}
Prints:
Foo1 constructor!!!
Foo2 constructor!!!
Foo2 destructor!!!
Foo1 destructor!!!
The trace of the program is:
Main starts
Initiallization of my_foo2_instance: Call to Foo2 constructor
First of all, Foo2 initializes its attributes: Call to Foo1 constructor
Foo1 has no attributes, so Foo1 executes its constructor body: cout << "Foo1 constructor" << endl;
After attributes initiallization, Foo2 executes its constructor body: cout << "Foo2 constructor" << endl;
End of main scope, so end of my_foo2_instance lifetime: Call to Foo2 destructor
Foo2 destructor executes its body: cout << "Foo2 destructor" << endl;
After the destructor, the lifetime of the attributes of Foo2 ends. So: Call to Foo1 destructor
Foo1 destructor executes its body: cout << "Foo1 destructor" << endl;
After the destructor, the lifetime of the attributes of Foo1 ends. But Foo1 has no attributes.
But what you forget is that a pointer its a basic type, so it has no destructor. To destroy the object pointed by the pointer (Thats is, finallize the life of the pointee object), use use delete operator in destructor body.
Destructor never deallocates anything on its own accord. Destructor will only implicitly call destructors for class subobjects and execute whatever code you put into the destructor's body. Since in your case the subobject ch is of raw pointer type, it has no destructor. So nothing will be done in your case. Since it is you who allocated the memory, it is you who's responsible for deallocating it. In short, yes, you do need that delete[] ch in your destructor.
If you want that memory deallocated automatically, use a smart pointer class instead of a raw pointer. In that case the destructor of your class will automatically call the destructor of the smart pointer subobject, which will deallocate memory for you. In your specific example an even better idea would be to use std::string to store the string inside the class object.
The heap corription in your case is caused by the fact that you allocate insufficient memory for your string, which leads to an out-of-bounds write in strcpy. It should be
ch = new char[strlen(_ch) + 1];
strcpy(ch,_ch);
The extra space is needed for the terminating zero character.
My take:
1) The short answer is no.
2) As for "why not", consider the following example:
cls create()
{
cls Foo("hello"); // This allocates storage for "ch"
return Foo;
} // Return variable is by value, so Foo is shollow-copied (pointer "ch" is copied).
// Foo goes out of scope at end of function, so it is destroyed.
// Do you want member variable "ch" of Foo to be deallocated? Certainly not!
// Because this would affect your returned instance as well!
Recommendations:
If you want to see whether your code leaks storage, you may use an excellent tool valgrind, http://valgrind.org/
As for what to read to understand this topic better, I would recommend the standard C++ literature, plus have a look at smart pointers, e.g. unique pointer
http://www.cplusplus.com/reference/memory/unique_ptr/
which will help you understand the topic and everything will be put to place.

Meaning of "~" (tilde) symbol in C++?

// AirlineTicket.h
class AirlineTicket
{
public:
AirlineTicket();
~AirlineTicket();
int getNumberOfMiles();
private:
int mNumberOfMiles;
};
I want now what is the meaning of ~AirlineTicket(); in this code?
I don't know the meaning of ~ (tilde).
It is the destructor.
It gets called when you destroy (reaching end of scope, or calling delete to a pointer to) the instance of the object.
In the context you're using it, it defines a destructor.
In other context such as the following one, it's also called bitwise negation (complement):
int a = ~100;
int b = ~a;
Output: (ideone)
-101
100
~ signs that it is a destructor and when ever the object goes out of scope, corresponding destructor is called.
When the destructor is called ?
Taking an example -
#include <iostream>
class foo
{
public:
void checkDestructorCall() ;
~foo();
};
void foo::checkDestructorCall()
{
foo objOne; // objOne goes out of scope because of being a locally created object upon return of checkDestructorCall
}
foo:: ~foo()
{
std::cout << "Destructor called \t" << this << "\n";
}
int main()
{
foo obj; // obj goes of scope upon return of main
obj.checkDestructorCall();
return 0;
}
Results on my system:
Destructor called 0xbfec7942
Destructor called 0xbfec7943
This example just serves to indicate when a destructor is called. But destructor is written only when the class manages resources.
When class manages resources?
#include <iostream>
class foo
{
int *ptr;
public:
foo() ; // Constructor
~foo() ;
};
foo:: foo()
{
ptr = new int ; // ptr is managing resources.
// This assignment can be modified to take place in initializer lists too.
}
foo:: ~foo()
{
std::cout << "Destructor called \t" << this << "\n";
delete ptr ; // Returning back the resources acquired from the free store.
// If this isn't done, program gives memory leaks.
}
int main()
{
foo *obj = new foo;
// obj is pointing to resources acquired from free store. Or the object it is pointing to lies on heap. So, we need to explicitly call delete on the pointer object.
delete obj ; // Calls the ~foo
return 0;
}
Results on my system:
Destructor called 0x9b68008
And in the program, you posted I don't see a need to write destructor. Hope it helps !
It's the class destructor. You might want to pick up an introductory text on C++ development, as destructors are a fundamental concept in OOP. There is a good reference site here, and the C++ FAQ is another good resource.
~AirlineTicket(); is the destructor for the class AirlineTicket
see this link for further reference
The destructor is called when you delete the object of that class, to free any memory allocated or resources being used by the object.
~ introduces a destructor. It's used because (a) it was available, ad (b) ~ is one (of several) mathematical notation for "not".
This indicates destructor of class.
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr380.htm