Below is the pattern of new/delete operators in my program. Valgrind says that memory is "definitely lost". I couldn't quite get where the leak is. Is there something wrong with my usage of new/delete operators.
class Generic
{
GenericInterface *gInterface; //GenericInterface is abstract class
public:
Generic ()
{
gInterface = NULL;
}
~Generic ()
{
delete gInterface;
}
void Create()
{
gInterface = new Specific();
}
};
class Specific : public GenericInterface
{
MyClass* _myClass;
public:
Specific()
{
_myClass = new MyClass;
}
~Specific()
{
delete _myClass;
}
};
int main()
{
Generic g;
g.Create();
}
valgrind says that memory is lost.
==2639== 8 bytes in 1 blocks are definitely lost in loss record 2 of 45
==2639== at 0x4026351: operator new(unsigned int) (vg_replace_malloc.c:255)
==2639== by 0x804D77C: Specific::Specific() (Specific.cc:13)
==2639== by 0x804DAFC: Generic::Create() (Generic.cc:58)
You are not following the rule of three. If your class manages resources that need to be cleaned up, you must declare a destructor, copy constructor, and copy assignment operator. Neither of your classes has a copy constructor or a copy assignment operator.
Really, you should almost certainly just be using a smart pointer like unique_ptr from C++0x; shared_ptr from Boost, C++ TR1, and C++0x; or scoped_ptr from Boost.
The likely issue causing this specific problem is that you have forgotten to make the base-class GenericInterface destructor virtual, so the wrong destructor is being called and the MyClass object that you dynamically create in Specific is never destroyed.
deleteing an object via a pointer to one of its base classes results in undefined behavior if the base class destructor is not declared virtual (that means bad things will happen, ranging from memory leaks to crashes).
Your GenericInterface destructor probably is not virtual, so only the GenericInterface destructor is getting called when gInterface is destroyed.
Does your GenericInterface class declare a virtual destructor? If not, the Specific class's destructor won't get called, and thus the "delete _myClass" line won't be executed.
Just another way C++ makes your life more interesting :)
In your Generic class destructor you should also check the gInterface pointer before deleting it. If Create() is not called before the object is destroyed it will cause problems. If your c++ compiler doesn't throw on new failures your other class may also do the same thing
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.
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.
I'm not quite sure I understand virtual destructors and the concept of allocating space on the heap right. Let's look at the following example:
class Base
{
public:
int a;
};
class Derived : public Base
{
public:
int b;
};
I imagine that if I do something like this
Base *o = new Derived;
that 8 Bytes (or whatever two integers need on the system) are allocated on the heap, which looks then something like this:
... | a | b | ...
Now if I do this:
delete o;
How does 'delete' know, which type o is in reality in order to remove everything from the heap? I'd imagine that it has to assume that it is of type Base and therefore only deletes a from the heap (since it can't be sure whether b belongs to the object o):
... | b | ...
b would then remain on the heap and be unaccessible.
Does the following:
Base *o = new Derived;
delete o;
truly provoke memory leaks and do I need a virtual destructor here? Or does delete know that o is actually of the Derived class, not of the Base class? And if so, how does that work?
Thanks guys. :)
You're making a lot of assumptions about the implementation, which may
or may not hold. In a delete expression, the dynamic type must be the
same as the static type, unless the static type has a virtual
destructor. Otherwise, it is undefined behavior. Period. That's
really all you have to know—I've used with implementations where
it would crash otherwise, at least in certain cases; and I've used
implementations where doing this would corrupt the free space arena, so
that the code would crash sometime later, in a totally unrelated piece
of code. (For the record, VC++ and g++ both fall in the second case, at
least when compiled with the usual options for released code.)
Firstly, the classes you declared in your example have trivial internal structure. From purely practical point of view, in order to destroy object of such classes properly the run-time code does not need to know the actual type of the object being deleted. All it needs to know is the proper size of the memory block to be deallocated. This is actually something that is already achieved by C-style library functions like malloc and free. As you probably know, free implicitly "knows" how much memory to deallocate. Your example above does not involve anything in addition to of that. In other words, your example above is not elaborate enough to truly illustrate anything C++-specific.
However, formally the behavior of your examples is undefined, since virtual destructor is formally required by C++ language for polymorphic deletion regardless of how trivial the internal structure of the class is. So, your "how delete knows..." question simply does not apply. Your code is broken. It does not work.
Secondly, the actual tangible C++-specific effects begin to appear when you begin to require non-trivial destruction for your classes: either by defining an explicit body for the destructor or by adding non-trivial member subobjects to your class. For example, if you add a std::vector member to your derived class, the destructor of the derived class will become responsible for (implicit) destruction of that subobject. And in order for that to work, you will have to declare you destructors virtual. A proper virtual destructor is called through the same mechanism as any other virtual function is called. That's basically the answer to your question: the run-time code does not care about the actual type of the object simply because the ordinary virtual dispatch mechanism will ensure that the proper destructor is called (just like it works with any other virtual function).
Thirdly, another significant effect of virtual destruction appears when you define dedicated operator delete functions for your classes. The language specification requires that the proper operator delete function is selected as if it is looked up from inside the destructor of the class being deleted. And many implementations implement this requirement literally: they actually implicitly call operator delete from inside the class destructor. In order for that mechanism to work properly, the destructor has to be virtual.
Fourthly, a part of your question seems to suggest that you believe that failing to define a virtual destructor will lead to "memory leaks". This a popular, but completely incorrect and totally useless urban legend, perpetuated by low-quality sources. Performing polymorphic deletion on a class that has no virtual destructor leads to undefined behavior and to completely unpredictable devastating consequences, not to some "memory leaks". "Memory leaks" are not the issue in such cases.
There is no problem in the size of the object being deleted - it is known. The problem solved by virtual destructors can be demonstrated as follows:
class Base
{
public:
Base() { x = new char[1]; }
/*virtual*/ ~Base() { delete [] x; }
private:
char* x;
};
class Derived : public Base
{
public:
Derived() { y = new char[1]; }
~Derived() { delete [] y;}
private:
char* y;
};
Then having:
Derived* d = new Derived();
Base* b = new Derived();
delete d; // OK
delete b; // will only call Base::~Base, and not Derived::~Derived
The second delete will not finalize the object properly. If the virtual keyword was uncommented, then the second delete statement will behave as expected, and it will call Derived::~Derived along with Base::~Base.
As pointed out in the comments, to be strict, the second delete yields an undefined behavior, but it's used here only for the sake of making the point about virtual destructors.
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.