memory leak when deleting derived class with base-class pointer - c++

I have an issue with a memory leak. I have a base-class pointer. From it, I use new to allocate different derived classes. Then, when I try to delete those classes with the reference (not typecasted), I get a memory leak. I researched the problem and found that I should add a virtual destructor to the base-class, but I tried this and I still have a memory leak; that is, according to my task-manager, the memory usage continues to rise with each allocation and deletion of the derived class using the base-class pointer. I tried making it an abstract destructor and added destructors to the derived classes, but I got an undefined reference error. I also tried typecasting the pointer as a derived-class pointer for the delete, but apparently this crashes the program.
Does anyone have any idea what I should do?
Example code:
class A {
public:
A();
~A() {};
virtual ~A(); /*or*/
virtual ~A()=0; /*or*/
/*or nothing?*/
}
class B: private A {
public:
B();
~B() {}; /*this?*/
/*or nothing?*/
}

How sure are you that there really is a memory leak? Normally, the task manager won't be much help here, since it cannot tell how much of the memory belonging to your process is actually allocated. Even memory that is freed still belongs to your process, and may be used at later times by the memory management (normally malloc-like system library).
Use a tool such as mallocdebug, valgrind, purify etc. to find out if there's really a memory leak. These tools will replace the malloc implementation by a new one that keeps track of allocated memory and reports memory that is not freed upon process termination.
Note: On most systems, memory that is freed from a process is not returned to the system before the process exits. It is availabe for new allocations from within the same process, though.

use virtual ~A();
I'd be surprised if virtual ~A()=0 is allowed.
With this code:
A* base = new B();
delete base;
the destructor for B then A will be called.
If you're really still leaking memory, then you have another leak elsewhere.

If you have a virtual destructor, the destructor(s) of your subclass(es) will all be called. no need to do any esoteric magic with abstract deconstructors or anything.
I would assume the memory leak is somewhere inside your object. Maybe you're calling new() on something in B's (or A's?) constructor, but you don't delete it. Without seeing more code, all I can say is "your destructor setup is fine".

You can use:
virtual ~A(){}
or
virtual ~A()=0;
// as long as there is also:
A::~A(){} // inline in the header file or non-inline in the cpp file.
This means that:
A* base;
...
delete base;
will call all the destructors of the derived classes in the correct order.
Note that a pure virtual destructor: virtual ~A()=0; can be useful if you need to have an abstract base class when no other member functions are pure virtual.

Related

Virtual destructor and memory deallocation

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.

Does the destructor get called automatically

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.

Unable to nail memory leak detected by valgrind

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

Is the whole object freed with a non-virtual destructor and a Base class pointer?

If a Base class does not have a virtual destructor (in order to avoid the vtable entry for instance) and the Derived class has only basic attributes, does it free all the memory allocated by new, when the pointer of the Base class is deleted? I know the destructor of the Derived class will not be called but I am wondering if the memory allocated by the whole object will be freed?
I assume also that calling delete on a Derived pointer will free the whole memory space.
Also, if it does not free the Derived class part of the memory, how does it work in the same case but with of a virtual destructor in the Base class, to know how much memory to free?
Example:
class Base {
public:
int a;
int b;
Base() {}
~Base() {}
};
class Derived : public Base {
public:
int c;
int d;
Derived() {}
~Derived() {}
};
int main() {
Base *p = new Derived();
delete p; // is memory allocated for Derived freed?
}
It's undefined behavior, so anything can happen. Quote from the standard [expr.delete]:
In the first alternative (delete object), if the static type of the object
to be deleted is different from its
dynamic type, the static type shall be
a base class of the dynamic type of
the object to be deleted and the
static type shall have a virtual
destructor or the behavior is
undefined.
Just don't do that.
I think it's a good idea to understand what actually happens though to understand why the standard has that requirement.
In your simple case, on a typical implementation, the memory will be freed regardless. That is because operator delete will call free(p). Since Base is the first non-virtual base class of Derived, it happens to be located at the beginning of the allocated memory block. And since free must know the size of the allocated block by its own bookkeeping (being a C function it doesn't know anything about sizes of types), it will deallocate the entire block.
However, since Base doesn't have a virtual destructor, delete p is resolved based on the static-type of *p (which is Base). Consequently, as you're seemingly aware, it will not call the destructor of Derived. If Derived had any non-trivial members or base-classes, those would not be destructed either, so any resources that they manage would be leaked.
When the class has a virtual destructor, the work of freeing the memory is delegated to the destructor. The reason is that, although free knows to determine the size of the block, it would still need to have the pointer to the beginning of it. Base can be at an arbitrary offset within Derived in the general case, therefore Derived destructor will be responsible for adjusting the pointer prior to freeing it. This also adds the need for a separate destructor that would destructor the object without actually freeing the memory; e.g. as a subobject of another derived type, or as explicit destructor call. And let's keep delete[] out of the discussion. When you mark your destructor as virtual, the compiler takes care of all this for you.
The bottom line is that the standard doesn't describe all these implementation details, leaving them instead to—um—the implementation. They could formulate some sensible criteria when deleting a non-virtual base would still be ok; but instead they went with the simple clear-cut "you have a virtual destructor then it's ok, otherwise it's not ok" rule.
Technically, the answer is 'unknown'. Deleting a pointer to derived from a pointer to base that has no virtual destructor is undefined behavior.
Practically speaking though, most implementations just fail to properly delete the stuff in the derived object.
Formally speaking, this is undefined behaviour, so you have no guarantees that the memory is freed, or indeed that your program does anything in particular. It may format your hard disk. It may not. In practice, the memory might well be freed in this case -- but you're daft if you rely on it, and you shouldn't do it. It's as simple as that.
Edit: I Was mistaken: Key prose from draft standard, emphasis mine: Section 5.3.5
3 In the first alternative (delete
object), if the static type of the
object to be deleted is different from
its dynamic type, the static type
shall be a base class of the dynamic
type of the object to be deleted and
the static type shall have a virtual
destructor or the behavior is
undefined. In the second alternative
(delete array) if the dynamic type of
the object to be deleted differs from
its static type, the behavior is
undefined.
There is a good chance the memory will be correctly freed. Just because the Standard doesn't assure this doesn't mean it won't work. It's hard to see how it could fail.
In the very particular case that you describe, all of the memory used by the derived class object will be freed when you don't have a virtual destructor. (If using non-virtual destructors always caused derived classes to leak memory, I don't think the language would allow inheriting from classes that used them!)
Remember, the DESTRUCTOR is not what frees the memory; "delete" frees the memory. The destructor is just a function that gets CALLED by delete.
Blah blah blah extensibility blah blah cause yourself trouble in the future blah blah careful with that etc. etc. etc. You know what I mean, obviously.

When virtual destructor is not needed even there is a virtual function, Why?

It says that if there is a virtual function, it is a good practice to have a virtual destructor. However, if the object is created on the stack but not on heap, do we still need to do that?
Regards,
Strictly speaking no - the virtual destructor is only necessary if the object will be destroyed via a pointer to reference to a base object.
If the static type at destruction time is the actual type of the object, then the correct dtor will be called regardless of whether it's virtual or not.
But if a class has virtual functions, the reason for that is generally so that it can be accessed through a pointer or reference to one of the objects bases. If the object is going to be destroyed through that mechanism, then having a virtual dtor will ensure the correct one is called. And if you have a virtual function, making the dtor virtual comes at next to no cost.
Yes since someone else could write new code that creates your object on the heap. It would be bad practice for your class to assume that it is always going to be created on the stack...
If you write an object with a virtual method, it is expected that you will use it through an interface/base object.
And it is half-expected you will own this object through a pointer (or a smart pointer). In that last case, you need the virtual destructor.
As most of the time, your code will be used by others, you can't predict they won't use the object through its base pointer... In fact, one day, you will perhaps use it this way, too...
Now, in your case, your object is created on the stack, which means that the compiler knows its type statically. Thus, when the object will be destroyed, the right destructor will be called directly, causing zero overhead.
Conclusion: As you said, it's simple good practice, and considering the limited (or zero) cost of a virtual destructor in most cases, it should be upheld.
Simple rule:
Provide either a public virtual destructor or a protected non-virtual destructor for each class that has virtual methods.
If instances of your class are meant to be deleted through a pointer to the base then the destructor must be virtual. If you class is not meant to be deleted through base pointers then making the destructor protected will block external code from deleting through a base pointer.
Note that you can use polymorphic behavior without deleting through base pointers: when you pass the object by reference or pointer but the lifetime is handled always at the most derived type, or using constructs like shared_ptr:
class base {
protected:
~base() {}
virtual void f();
};
class derived : public base {
public:
void f();
};
int main()
{
shared_ptr<base> sp( new derived );
base *b = new derived;
//delete b; // compile time error: cannot access ~base
// if it was allowed it would be UB
delete static_cast<derived*>(b); // correct (static_cast is ok, we know the type)
} // sp goes out of scope: delete at ´derived´ level
One of the aims of OOP is code-reuse. So while you may be allocating objects on the stack at present, that may not always be the case under re-use and maintenance or in a team development environment.
It is generally a trivial overhead that significantly increases the utility, reusability and safety of your code.