Can anyone tell me what happens with object's memory if I forget to declare a destrucor in a C++ class? I mean, whether it is freed or causes memory leak?
An example or demo will be appreciated.
Thanks in advance.
It's often considered good practice to define a destructor for any non-trivial class (see the Rule of Three). However, in modern C++ (i.e. C++11 onwards), it's not as necessary as it used to be.
If your class is not inherited from anything else, any direct members (such as variables and objects) will be properly destroyed by the default destructor provided by the compiler. Similarly, if your object owns any heap-allocated objects which are wrapped in smart pointers, they will be destroyed safely too.
A problem arises if your object owns any heap-allocated data via raw pointers. The implicit destructor has no way of knowing what to do with them, so you will need a custom destructor to clear them up. For example:
class MyClass
{
int m_data1;
std::string m_data2;
std::shared_ptr<Widget> m_data3;
Widget *m_data4;
};
In the above example, members m_data1, m_data2, and m_data3 will all be cleared-up correctly without a custom destructor. However, the object pointed to by m_data4 will not be cleared up automatically. If it was allocated by MyClass, then it will usually result in a memory leak (unless it's getting freed by something else).
With all of that said, inheritance changes things in an important way. If your class is inherited by anything else then you should probably always give it a virtual destructor. If your object is deleted via a pointer to an inherited class, and that class does not have a virtual destructor, then the sub-class' destructor will never be called, potentially resulting in memory leaks.
For example:
class Parent
{
public:
Widget m_data1;
}
class Child : public Parent
{
public:
Widget m_data2;
}
int main()
{
Parent *ptr = new Child;
delete ptr; // <-- clears-up Parent but not Child
}
In the above example, ptr is of Parent type, so the delete only knows about the Parent part of the object. That means only m_data1 will be cleared-up correctly. Without a virtual destructor, it doesn't know about the Child part of the object, so m_data2 will not be cleared-up correctly (its destructor will never be called).
If destructor is not declared, compiler will generate destructor, that will call destructors of all members of object. Leak can be only if you are working with raw-memory (C files, memory allocation etc).
It depends on the class' data members. If the class manages resources, then it needs a destructor to release them (you should also provide a copy constructor and assignment operator, or make the class non-copyable and non-assignable).
If the class has built-in data members, or data members that manage their own resources, then the implicitly generated destructor is enough. It will call the destructor of all data members.
Related
Recently I am studying OOP using C++, and I am quite confused when I should use destruction function of my own in the following case:
class T1{
private:
int data;
public:
T1(){...};
~T1(){}; // should I write my own function here?
};
class T2{
private:
T1* pointer_to_T1;
public:
T2(){...};
~T2(){}; // should I write my own function here?
};
class Node{
public:
int data;
Node* next;
};
class T3{
private:
int size;
Node* head;
public:
T3(size){
head = new Node[size];
}
~T3(){}; // should I write my own function here?
};
There are three comments in my program above to clarify my question. I hope you could explain them and I would appreciate it if you could give me a general rule.
In case of class T3 you are allocating new memory, so you will have to delete the allocated memory segment in destructure.
class T3{
private:
int size;
Node* head;
public:
T3(size){
head = new Node[size];
}
~T3(){
delete[] head;
};
};
I'll attempt to answer in a general way not specific to your code snippets.
Two general scenarios commonly present themselves in which you'll need a non-trivial destructor. This is not a complete list; just the most common scenarios.
1) In a (polymorphic) hierarchy. If your class is a base class, intended to be derived from, there is a very good chance that your base class should have a non-trivial destructor. Moreover, that destructor should probably be virtual. This makes it possible to delete derived-class objects through the base-class pointer, like this:
class Foo
{
public:
virtual ~Foo(){}
};
class Bar : public Foo
{
};
int main()
{
Foo* obj = new Bar;
delete obj;
}
Without the virtual destructor, this program would exhibit Undefined Behavior.
2) When your class has members need more than trivial destruction. A simple example is if your class has a member that is a raw pointer (as in not a smart pointer) that was created using new. That pointer will need to be deleted, and the destructor is probably the right place to do it. A good indication that your class manages non-trivially-destructible members is if your class has either a copy constructor or a copy assignment operator (operator=). If your class has either then it probably needs both of them plus a destructor to handle whatever was assigned. (See Rule of Three) This isn't the only indication however -- you could have only a default constructor and still need a destructor. It depends on what your class does.
The destructor of a class should perform all actions needed when the object is deleted.
For example it need to free all the memory that was dynamically allocated by the class.
You should write a destructor when your class is a base class, and you expect polymorphic destruction, and when you want some logic to be ran when the object is destroyed.
If the object owns and manages resources, you probably need a constructor. Don't forget about the copy and assignment operators.
The object should cleanup after itself.
IE, if you ever allocate memory in your object, possibly being done in the constructor, then you should deallocate that memory in the destructor.
The destructor is meant to cleanup after your object. So it is also possible that you can do anything to help you do that.
Class T1 does not require to define explicitly the destructor. It will be enough to have the destructor implicitly defined by the compiler.
Class T2 needs to define the destructor explicitly that to deallocate its data member having type pointer. Otherwise there will be a memory leak.
Class Node does not need to define the destructor explicitly. It is class T3 that has to delete all pointers of class Node because it is it that controls the allocation and deallocation of nodes.
You need to declare a destructor:
if the class manages resources that need to be manually released when it's destroyed;
if it's intended to be a polymorphic base class, in which case it needs a virtual destructor to allow polymorphic deletion.
In the first case, you'll also need to provide, or delete, a copy constructor and copy-assignment operator; otherwise you could end up with two or more objects trying to manage the same resource. This is known as the "Rule of Three". Usually, you can use ready-made classes like containers and smart pointers to manage memory for you; so there's usually no need to muck around with destructors yourself. Some people refer to this as the "Rule of Zero".
In the second case, the destructor doesn't have to do anything (assuming the class isn't trying to manage any resources), it just needs to be virtual.
For your specific examples:
T1 doesn't need a destructor
T2 might, depending on whether it's supposed to manage whatever the pointer points to. If it does, then consider replacing the pointer with a smart pointer like std::unique_ptr<T1>.
T3 probably does, since it appears to be managing the dynamic array. You'll also need to consider the Rule of Three; or consider using std::vector<Node> to manage the array automatically.
I can't help reading the bulk of forum posts on destructors and getting totally confused.
Some say to call the destructor (with delete) once for each call to new. Some say the destructor automatically gets called in a variety of circumstances i.e. when the pointer is reassigned, when the object goes out of scope. Some suggest the pointer going out of scope while being a return value where the object exists as a copy of its former self, (does this then need explicit destruction as it was originally created with a new?
There seems to be some suggestion that calling the same destructor more than once will corrupt memory so all delete calls should be partnered with *pointer = NULL; to avoid corruption. If not then some more advanced object management system would require implementing, or an iron-fisted rigour of ownership.
I can't seem to make any sense of discussions on calling sequence of destructors, i.e. does the call 1) originate at the base superclass and cascade down to the specific class, calling all virtualised destructors on the way, 2) originate at the instantiated class and move up to the superclass, or 3) originate at the particular cast the class has when it goes out of scope, then traverse both toward the instantiated and base class. Do cascading destructors
Ultimately I simply don't know strictly how or when to delete objects if ever, whether objects are responsible for deleting all objects they reference, how to cleanly handle a proper object-oriented deletion routine where an object is referenced multiple times, it's just a mess in my head. As you can see I can't really formulate a single solid question to ask, am really hoping someone can offer a clean and concise discussion of if not the single 'correct' approach, at least the industry best practice to object deletion.
There are 3 types of allocation for which destructors are called in different ways:
Automatic allocation
These objects reside in automatic memory (trivially, the stack):
int main()
{
A a;
//...
}
The destructor of a is automatically called when a goes out of scope (closing }).
Dynamic allocation
Objects reside in dynamic memory (the heap). They are allocated with new and in order for the dstructor to be called, you need to call delete:
int main()
{
A* a = new A;
delete a; //destructor called
}
In this case it was probably suggested you should assign NULL to a after the delete. There are two schools of thought regarding this (I personally wouldn't suggest it). The motivation would be that you could possibly call delete again on a and crash the program if you don't set it to NULL. Which is correct. But if you do call delete again, that's already a bug or something wrong in the logic, which shouldn't be masked by making the code appear to run correctly.
Static allocation
Objects reside in static memory. Regardless of where they are allocated, the destructor is automatically called when the program ends:
A a; //namespace scope
int main()
{
}
Here, As destructor is called when the program terminates, after main finishes.
The C++ language leaves memory management in the hand of the programmer, that is the reason for which you can find that level of confusion.
Repeating what Luchian Grigore said there are three main types of memory
automatic storage (stack)
dynamic storage (heap)
static storage
If you allocate an object in automatic storage the the object will be destroyed once the scope is terminated; for example
void foo() {
MyClass myclass_instance;
myclass_instance.doSomething();
}
in the above case when the function terminates myclass_instance is destroyed automatically.
If you instead allocate an object in the heap with new then it's your responsibility to call the destructor with delete.
In C++ also an object can have sub-objects. For example:
class MyBiggerClass {
MyClass x1;
MyClass x2;
...
};
those sub-objects are allocated in the same memory the containing object is allocated to
void foo() {
MyBiggerClass big_instance;
MyBiggerClass *p = new MyBiggerClass();
...
delete p;
}
in the above case the two sub-objects big_instance.x1 and big_instance.x2 will be allocated in automatic storage (stack), while p->x1 and p->x2 are allocated on the heap.
Note however that you don't need in this case to call delete p->x1; (compile error, p->x1 is not a pointer) or delete &(p->x1); (syntactically valid, but logical mistake because that it wasn't allocated explicitly on the heap, but as a sub-object of another object). Deleting the main object p is all that is needed.
Another complication is that an object may keep pointers to other objects instead of including them directly:
class MyOtherBigClass {
MyClass *px1;
MyClass *px2;
};
in this case it will be the constructor of MyOtherBigClass that will have to find the memory for the sub-objects and it will be ~MyOtherBigClass that will have to take care of destroying the sub-objects and freeing the memory.
In C++ destroying a raw pointer doesn't automatically destroy the content.
Base classes in simple cases can be seen just as hidden embedded sub-objects. I.e. it's like if an instance of the base object is embedded in the derived object.
class MyBaseClass {
...
};
class MyDerivedClass : MyBaseClass {
MyBaseClass __base__; // <== just for explanation of how it works: the base
// sub-object is already present, you don't
// need to declare it and it's a sub-object that
// has no name. In the C++ standard you can find
// this hidden sub-object referenced quite often.
...
};
This means that the destructor of the derived object doesn't need to call the destructor of the base object because this is taken care by the language automatically.
The case of virtual bases is more complex, but still the invocation of base destructors is automatic.
Given that memory management is in the control of the programmer there are a few strategies that have emerged to help programmers avoiding making a mess of intricate code that always ends up in object leaks or multiple destruction.
Plan carefully how you are going to handle lifetime of the instances. You cannot just leave this as an afterthought because it will be impossible to fix later. For every object instance it should be clear who creates and who destroys it.
When it's impossible to plan ahead of time when an object should be destroyed then use reference counters: for every object keep track how many pointers are referencing it and destroy the object once this number reaches zero. There are smart pointers that can take care of this for you.
Never keep around a pointer to an object that has already been destroyed.
Use containers that are classes designed explicitly to handle the lifetime of contained objects. Examples are std::vector or std::map.
If your code calls new, then it should call delete as well, yes. Except if you are using smart pointers (which will call delete for you when the pointer gets destroyed). Whenever possible, you should use smart pointers and use vector or string to avoid having to manually allocate memory using new - if you don't call new, you don't need to worry about making sure delete is called -> no memory leaks, and no problems with objects being destroyed at the wrong time, etc.
Calling delete multiple times for the same instance is definitely a bad idea.
If we have this:
class A
{
int *p;
public:
A() { p = new int[10]; }
~A() { delete [] p; }
};
class B
{
A a;
~B() { ... }
...
};
class C : public B
{
...
~C() { ... }
}
...
C *cp = new C;
....
delete cp;
then the destructor of C gets called by delete. The destructor of B is called by the C destructor, and the destructor of A gets called by the B destructor. This is automatic, and the compiler will "make sure this happens".
And if we don't call new:
...
{
C c;
...
} // Destructor for C gets called here (and B and A as describe above)
Let's say we have a class called memoryCounter that tries to catch memory leaks caused by MyClass class.
class memoryCounter
{
public:
static int MyClassCount;
};
int memoryCounter::MyClassCount = 0;
Let's also say we put the following lines in the constructor and destructor of MyClass (and any other constructors that it has, assuming also that we don't modify the MyClassCount anywhere else outside the constructors/destructors):
MyClass()
{
memoryCounter::MyClassCount++;
}
virtual ~MyClass()
{
memoryCounter::MyClassCount--;
}
Now, can we be absolutely sure that if memoryCounter::MyClassCount contains zero, then all the memory we allocated this far was freed and there are no leaks? Or can there be a situation when the variable will contain zero, but there will be allocated memory that we did not free (please consider the situations where 'MyClass' is a base or derived class, too)?
No, you can't. There can be other constructors as well (copy-constructor at least). You don't count them.
Also you can't count the destruction of static variables so easy, because they are destructed after main exits
If the count is zero, then there are no instances of MyClass. It applies regardless of whether the MyClass object is a complete object, or a base class sub-object, or for that matter a member sub-object. That doesn't necessarily mean there are no memory leaks, since maybe MyClass itself leaks memory.
Something to watch out for is the default-generated copy constructor. You say to assume that "any other constructors that it has" increment your global count, but it's easy to miss the constructor that doesn't appear in the code. You could have applied the rule of three here - you define a destructor so you should have defined a copy constructor. Mind you, the rule also tells you define a copy assignment operator, which in this case is not needed.
Who says that only constructors allocate memory? If some non-constructor member function (static or not) allocates memory, and the destructor does not clean up properly, you have leaked that memory.
So, the answer is no. You have counted class instances created through the standard constructor. No more, no less.
You're assuming that MyClass (and anything derived from it) are correctly written. In particular, this leak won't be detected:
class BadClass : private MyClass
{
public:
BadClass() { int *x = new int(5); }
}
What your counter does is tell you that you've had one destruction for each construction, which means nobody has leaked any 'MyClass' objects.
But that's not the same as no memory leaks.
My question is simple, but I haven't been able to find the question anywhere.
If I have a class like such
class A {
vector<int> data;
}
When an instance of A gets destroyed will data also get destroyed properly, or should I write a destructor for A that calls data's destructor? Basically I worried about whether the dynamic memory of vector will not be freed when an instance of A is destroyed. I suspect the answer is that data is freed properly, but I don't want to find out I'm wrong the hard way.
Further, if A was a struct would the destructor for data get called when a local instance of A falls out of scope?
Yes, data will be destroyed automatically, you need not do anything to achieve it. vector will handle the cleaning up of the dynamic memory allocated by it. The vector's destructor will be called automatically when an instance of A is destroyed.
There is no difference in behavior irrespective of whether A is a class or struct.
No need, data member's destructors are always called.
An explicit destructor is useful manual memory management
struct a{
int* ip;
a()
: ip(new int(5))
{ }
~a() { delete ip; }
};
That said, you should generally speaking use RAII containers (such as smart pointers) so I personally rarely write dtors there days.
And exception to that is to declare a base classes dtor as virtual.
struct base {
virtual ~base() {}
};
struct child : public base {
//base and child destructor automatically called
}
A default-destructor is created automatically by the compiler if you do not define one yourself. In general, you do not need to create your own destructor unless you have pointer data-members that "own" the memory they point to, and/or you are designing your class to be derived by other classes, at which point you would want to at least declare an empty virtual destructor.
In all cases, both with your own destructor, as well as the default compiler-created destructor, all destructors for non-static data-members as well as any base-classes of the current class are called at the end of the destructor and before the destructor function itself returns.
Lets say, for example, that I have a class that requires the use of some old C stuff (like pthreads or something), so for one reason or another, I've ended up with a malloc() call in my constructor, like so:
class Foo
{
public:
Foo()
{
someMutex = malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(someMutex);
someString = new string("yay string!");
}
private:
pthread_mutex_t * someMutex;
string * someString;
}
It seems like there is a lot of misinformation about destructors out there. I keep seeing examples of explicitly defined destructors calling delete on pointer based members, but I also keep reading that I don't need to explicitly define a destructor for a class to manage memory; all I need a destructor for are things like file handle cleanups and the like.
Thus leads to my question then: Even though someMutex was allocated with malloc and not the C++ new command, will the implicitly defined destructor still take care of it, or do I have to do it?
Also, lets just settle another question of mine, since its so closely related. In the class above, do I need to explicitly define a destructor in order to call delete on someString, or is that taken care of for me?
Not only do you need to define a destructor to do the cleanup, you also need to declare (and optionally define) a copy constructor and copy assignment operator for your class, to ensure that copies are made correctly.
The implicitly-defined destructor destroys member variables. So, for example, if you had a member variable of type string, the destructor will destroy that variable all on its own. However, the destructor for a pointer (like string*) is a no-op: you are responsible for destroying the pointed-to object.
You also need to define the copy operations for this class, or at least suppress generation of the default copy operations that the compiler provides for you. Why? Because by default, the copy operations just copy each member variable. So, if for example you were to write:
{
Foo x;
Foo y(x);
} // Uh oh
Both x and y are destroyed at the end of the block. At this point, both x and y point to the same dynamically allocated mutex and string, so the mutex and string would be destroyed twice (once for x and once for y).
The better option is not to use manual memory allocation at all. Rather, you should make someString a direct member of the class (i.e., declare it string someString;) or you should use a smart pointer of some kind to manage its lifetime (like unique_ptr or shared_ptr). Similarly, you should use a smart pointer with a custom deleter to manage the lifetime of the mutex, unless your class is noncopyable, in which case you can make the mutex a direct member of the class.
Yes, you have to define a destructor and destroy your objects (someMutex and someString).
But, as you have allocated someMutex with malloc, you must free it with free.
Take care for not to mix them.
Remember:
allocated with malloc, freed with free
allocated with new, freed with delete
allocated with new[], freed with delete[]
Instead of storing a pointer to a string in your class, I'd just store an instance of string as a data member (using "stack semantics").
Moreover, instead of storing a pointer to a "raw" pthread_mutex_t, I'd define a C++ class to wrap this pthread_mutex_t resource using RAII (creating the pthread_mutex_t in its constructor, and destroying it in its destructor), and then I'd store an instance of this C++ class as a data member of Foo.
//
// C++ RAII wrapper on raw C pthread_mutex_t resource.
//
class PThreadMutex
{
public:
// Creates a pthread_mutex_t.
PThreadMutex()
{
pthread_mutex_init(&m_mutex, ...);
// Check for errors, and throw exceptions on errors
}
// Destroys a pthread_mutex_t
~PThreadMutex()
{
pthread_mutex_destroy(&m_mutex);
}
// Other member functions
// ...
// May define move constructor and move assignment operator for C++11
// ...
private:
pthread_mutex_t m_mutex;
};
class Foo
{
public:
Foo()
: m_someString("yay string!")
// m_someMutex initialized by its default constructor
{
}
~Foo()
{
// Nothing to do: C++ compiler will call the destructors
// of class data members, releasing their associated resources.
}
private:
//
// Class "building blocks":
//
PThreadMutex m_someMutex;
string m_someString;
};
In this way, the compiler-generated destructor for Foo will automatically call each data members destructors, releasing their resources.
In general, each "raw" C resource (pthread_mutex_t, FILE *, etc.) should be wrapped in a C++ class using RAII, and instances of these classes (like they were kind of "building blocks") should be used as data members of other classes.
This helps simplify your code (and writing exception-safe code as well); if you use this pattern you can achieve a good level of code safety and composability.
No, destructor shouldn't delete those data (it may be pointer to memory allocated somewhere else in your application). So you have to write your own destructor.
And one more thing. Once you allocate memory with malloc you should free it with free().
Whether you need to define a destructor or not depends of if the current object OWNS the created objects or it just create them for some other object to manage, respectivelly.
When you allocate heap memory with malloc() you should free it with free().
When you create objects with new, then you must delete it with delete.
When you create an array with new[], then you must delete it with delete[].
Implicit destructors destroy member variables but in your case they are pointers so memory allocated for the pointers thenselves will be recovered, but not the allocated memory you just malloc'ed.
Another option is using a "smart pointer" (http://en.wikipedia.org/wiki/Smart_pointer), which will actually delete the pointed object when the current object is deleted (or get out of scope).