I am using dynamic memory allocation in my code, and am running into issues when trying to delete a pointer to a subclass. I find that the memory originally allocated is not freed when I use the delete keyword. The functionality works fine with the original base class.
This is an issue because I'm running the code on an arduino and the RAM gets eaten up quickly then crashes.
Here's some example code:
class Base
{
public:
Base(){
objPtr = new SomeObject;
}
~Base(){
delete objPtr;
}
SomeObject* objPtr;
};
class Sub : public Base
{
public:
Sub(){
objPtr = new SomeObject;
}
};
// this works fine
int main()
{
for (int n=0;n<100;n++) // or any arbitrary number
{
Base* basePtr = new Base;
delete basePtr;
}
return 0;
}
// this crashes the arduino (runs out of RAM)
int main()
{
for (int n=0;n<100;n++) // or any arbitrary number
{
Sub* subPtr = new Sub;
delete subPtr;
}
return 0;
}
I imagine it has something to do with the syntax of the destructor in the base class. Even if I make a custom destructor for the subclass, the same issues occur.
Any ideas?
In C++, constructors are called upwards in the hierarchy, that is, when you create Derived, Base() is executed before Derived(). This means that you are running objPtr = new SomeObject; twice, and only deleting it once.
You should also make your base class destructor virtual, especially if you will ever delete Derived instances from a Base ptr.
You should make the base class' destructor virtual.
virtual ~Base(){
delete objPtr;
}
Sub::Sub() constructor allocates a second extra SomeObject
after a first one was allocated by Base::Base() super constructor
and the second allocated pointer is assigned to objPtr provoking a leak.
Note: Base::Base() is implicitly called by Sub::Sub()
Solution: just remove needless allocation in Sub::Sub()
Another suggestion: make your Base destructor virtual as is recommended with inheritance
virtual ~Base(){
delete objPtr;
}
When you create the derived class it calls the Base class constructor first and then Subs constructor, you can see this here:
class Base
{
public:
Base(){
std::cout << "Base() ctor" <<std::endl ;
objPtr = new int;
}
~Base(){
delete objPtr;
}
int* objPtr;
};
class Sub : public Base
{
public:
Sub(){
std::cout << "Sub() ctor" <<std::endl ;
objPtr = new int;
}
};
So you end up calling new twice once in Base and then the second time in Sub. The memory allocated in Base is then lost and you have a leak. You also need to make the destructor virtual for it to work correctly with derived classes.
Memory for that pointer is allocated twice. So you will never free all the memory you new for it. Just make the pointer a private member and allocate it only in base class.
Related
My problem is, that when I'm using inheritance class, my base class is deleting 2 times (the copy from inheritance too). Is there a chance to not make a copy of base class? Or not delete it?
#include <iostream>
using namespace std;
class base {
public:
base() { cout << "*B"; }
~base() { cout << "~B"; }
};
class restaurant : virtual public base {};
int main() {
base* d1 = new base;
restaurant restaurant;
delete d1;
return 0;
}
The output is *B*B~B~B but I would like to have *B*B~B because I'm not deleting restaurant, only base object.
You're not deleteing restaurant, but you didn't new it either; it's allocated in automatic storage ("the stack"), not dynamic storage ("the heap"). Objects in automatic storage have their destructor called when they go out of scope. This is why the restaurant destructor is still being called in this case.
If you'd written:
restaurant *restaurant = new restaurant;
you'd see the behaviour you're expecting. Of course, by calling new without a matching delete you will be leaking the object, so this is not recommended.
Firstly, objects with automatic storage are automatically deleted a the end of a scope. So declaring restaurant restaurant; will construct a restaurant but will also delete it automatically at the end of the main function.
Try this:
struct A {
A() { std::cout << "A()"; }
~A() { std::cout << "~A()"; }
};
struct B : A {
B() { std::cout << "B()"; }
~B() { std::cout << "~B()"; }
};
auto main() -> int {
B b;
} // b destroyed here
The output is:
A()B()~B()~A()
It behave like a stack. First, the base class is constructed, then the derived class. Then, it destroy the derived first and the base class at the end.
This behaviour is extremely important for most C++ idiom.
Consider this:
struct A {
A() : arr(new int[3]{1, 2, 3}) {}
~A() { delete[] arr; }
int* arr = nullptr;
};
struct B : A {
B() {}
~B() {}
auto stuff() -> int {
return std::accumulate(arr, arr + 3, 0);
}
};
auto main() -> int {
B b;
return b.stuff(); // returns 1 + 2 + 3
}
What would happen if the constructor A() was not executed first? The array would be null. That would be bad.
Also... what would happen if the destructor ~A() was not executed? That would be a memory leak. That would be super bad.
Constructors and destructors have a guaranteed execution and a well defined order. This is why you don't have to call super() and ~super() in all of you constructors and destructor. Because you could forget to call it. Destructor and constructor is not something you want to forget to call, or else there would be no advantages over just using free function like in C.
The output is expected output.
I have added comments in your main function code.
int main() {
//Create base class object and constructor will be called
//This object is allocated on heap
base* d1 = new base;
//Create derived class object
//first constructor of base and then derived (if defined) will be called
//This object is allocated on stack
restaurant restaurant;
//Free memory and Call destructor of base class object
delete d1;
return 0;
//After bracket, stack object will go out of scope and destructor will be called.
//First derived (if defined) class destructor and then base class destructor.
}
To get expected output : *B*B~B
restaurant *restaurant = new restaurant;
But if you don't delete it then it will create memory leak in your program.
I believe It's C++ but it may be C? Its been a while since I looked at C++ so I didn't end up finding the bug. I was asked this question in an interview and didn't have an answer. I obviously didn't get the job but now I'm curious to find the answer.
#include<iostream>
class Base {
public:
Base() {
std::cerr<<"constructing Base " << this << std::endl;
i = new int;
}
~Base() {
std::cerr<<"destroying Base " << this << std::endl;
delete i;
}
private
int* i;
};
class Derived : public Base {
public:
Derived() {
std::cerr<<"constructing Dervied " << this << std::endl;
d = new double;
}
~Derived() {
std::cerr<<"destroying Derived " << this << std::endl;
delete d;
}
private
double* d;
};
int main(int argc, char** argv) {
using namespace std;
int ret = 1;
Base* thePtr = new Derived;
delete thePtr;
return ret;
}
Thanks in advance!
The Base's destructor is not virtual. This will leak the Derived::d pointer, at best.
Actually, it's undefined behaviour to delete a pointer of derived class through a base class pointer without virtual destructor (thanks to GManNickG)
You should mark Base class destructor as virtual. In your code Base class destructor isn't virtual & base class pointer is pointing to Derived class object so by default destructor will be called of Base class unless it is marked as virtual. This will leak dynamically allocated memory of Derived class data member d & invokes undefined behaviour.
Let me make a list...
Base destructor is not virtual.
It's using raw pointers instead of smart pointers
In fact, it doesn't need pointers, new and delete at all
And therefore, it doesn't actually need destructors.
Also Derived is spelled Dervied
... and it won't compile.
Your base class destructor should be declared virtual, it looks like
cpp
virtual ~Base()
{
std::cerr<<"destroying Base " << this << std::endl;
delete i;
}
you can find it here http://www.programmerinterview.com/index.php/c-cplusplus/virtual-destructors/
Virtual destructors are useful when you can delete an instance of a derived class through a pointer to base class:
there is a major problem with the code above: the destructor for the "Derive" class does not get called at all when we delete basePtr,
The construction of derived object follow the construction rule but when we delete the "b" pointer(base pointer) we have found that only the base destructor is call.But this must not be happened.
To do the appropriate thing we have to make the base destructor virtual. it's similar to the run-time polymorphism, so that the compiler will find this is a base pointer but point to the derived class, and automatically bound derived class destructor for it
In the code below, why is the ~Derived() destructor called automatically?
#include<iostream>
using namespace std;
class Base
{
public:
virtual ~Base()
{
cout << "Calling ~Base()" << endl;
}
};
class Derived: public Base
{
private:
int* m_pnArray;
public:
Derived(int nLength)
{
m_pnArray = new int[nLength];
}
virtual ~Derived()
{
cout << "Calling ~Derived()" << endl;
delete[] m_pnArray;
}
};
int main()
{
Derived *pDerived = new Derived(5);
Base *pBase = pDerived;
delete pBase;
return 0;
}
Because your base class destructor is virtual
virtual ~Base();
the call to delete on a pointer to a base class results in virtual call to destructor and as any virtual call is dispatched to matching function in derived class. It is not only good, but necessary: otherwise the behavior is undefined.
This is crucial for a derived classes which destructor is not an empty function. Non-virtual call would otherwise result in calling base class destructor, derived resources being leaked, etc.
When you have at least one virtual function in a class, then the compiler creates a single table for the class listing the member function pointers. Consider:
struct Base
{
virtual ~Base() { };
int n_;
};
In pseudo-code you can imagine the compiler adding:
void* Base::__virtual_dispatch_table[] = { (void*)&Base::~Base };
Then, when you have an actual object of type Base it will have an extra hidden data member that points to the Base::__virtual_dispatch_table (the "VDT"):
Variable definition Memory layout
------------------- -------------
Base myBase; int n_;
void** __p_vdt = Base::__virtual_dispatch_table;
Now, if you have a Base* p and delete p;, the compiler says "hey - it's virtual - I won't hardcode a call to Base::~Base, instead I'll generate code that does something like this pseudo-code:
void (Base::*p_destructor) = p->__p_vdt[0]
*p_destructor(p); // "p" will provide the "this" value while the destructor runs
Why would you want to do all that? Because when you come along with a Derived object...
class Derived: public Base
{
private:
int* m_pnArray;
...
...the compiler can create a separate virtual dispatch table...
void* Derived::__virtual_dispatch_table[] = { (void*)&Derived::~Derived };
...andd lay out the Derived object's memory like this:
Variable definition Memory layout
------------------- -------------
Derived derived; int n_;
void** __p_vdt = Derived::__virtual_dispatch_table;
int* m_pnArray;
Notice that the __p_vdt is in the same relative location within the object layout, but now points to the Derived class's virtual dispatch table?
Now, if you create a Base* to derived, the exact same code needed to call the destructor for a Base object, which - in case you've lost track - was...
void (Base::*p_destructor) = p->__p_vdt[0]
*p_destructor(p); // "p" will provide the "this" value while the destructor runs
...can be run but will end up using the Derived object's __p_vdt value of Derived::__virtual_dispatch_table, and finding the Derived class's destructor.
Because it allows you to treat any Base object (which may in fact be a Derived) as an object that you can delete.
In this case, if delete pBase didn't call the Derived destructor, the data held by m_pnArray would never get deleted, i.e. a "memory leak" would occur.
When you call
delete pBase;
It looks at the virtual function table of pBase to find the appropriate destructor to begin unwinding at, and it finds Derived::~Derived and then works its way down the stack.
I have a class hierarchy that's three levels deep, like this:
class A {
public:
virtual ~A() {}
}
class B : public A {
public:
virtual ~B() {}
void foo(E *e) {
e->remove(this);
}
}
class C : public B {
public:
~C() {}
}
class E {
public:
void remove(A *a) {
delete a;
}
}
Ok so what I am wondering is what happens when I call foo() on an object of C. Is it going to remove the entire object or only the B and A part of the object, and leave the C part still in memory?
Is it going to remove the entire object or only the B and A part of the object, and leave the C part still in memory?
No. It will "do the right thing" (that is, delete the most derived subobject, run all its destructors etc.) provided A (that is, the static type of the pointee of the pointer you delete) has a virtual destructor (and if class A has a virtual destructor, all its descendants have it, too). This holds for multiple inheritance, too.
Thanks to the virtual destructor in A the code would work correctly destroy the entire instance of C.
delete will always release the memory for the whole object pointed to.
This doesn't apply to called destructors however: It will try to call the destructor of the static type of the object to delete.
In a polymorphistic scenario, this is often not what you want. Consider this:
struct Base { };
struct Derived : Base
{
int* i;
Derived() : i(new int) { }
~Derived() { delete i; }
}
void bad()
{
Base* b = new Derived;
delete b;
}
bad() causes a memory leak, because Deriveds destructor will never be called. This is because the static type of b is Base*, thus Base::~Base will be called. There is no destructor defined in Base, so the default implementation provided by the compiler executes, which does nothing in this particular example.
This however does not apply to your example: You made the root class' destructor virtual, so all derived classes' destructors will be executed as part of the destructor call.
#include <iostream>
using namespace std;
int *p1;
struct base
{
base():a(10){}
int a;
~base()
{
cout << "~base()\n";
}
};
struct derive:public base
{
derive():b(5){
p1=&b;
cout << p1 << "\n";
}
int b;
~derive()
{
cout << "~derive()\n";
}
};
int main()
{
base *p = new derive;
delete(p);
cout << *p1;
return 0;
}
I think b of derive shoule not be deleted,but what p1 pointed was deleted.
how it works when I delete pointer of a base class that was pointed to an derive class when no dynamic inherit occured?
sorry for my english.
It's undefined behavior, because the base class destructor is not virtual. UB means anything can happen.
Don't delete a derived object through a base class if the base class doesn't have a virtual destructor.
What one would expect with following code
base *p = new derive;
delete(p);
is that the derive object pointed to by p is cleaned up correctly.
This can only be done when the base class has a virtual destructor. This is not the case here, so whatever cleanup that happens in the derive destructor will not happen, which is an unhealthy situation (or as put more technically by Luchian: undefined behavior).
I am not 100% I understand the question, and it has been awhile since ive used c++, but I will give it a shot.
Generally if you have an object that is going to be allocated dynamically you need to have 3 things, that my teachers used to call "The trilogy of evil".
Copy Constructor
Assignment Operator
Virtual Destructor
the first two have to do with making "deep copies" while the third is what we are concerned with.
You need to mark your destructor virtual to add it to the objects virtual table, that way the destructors will call up a chain.
so:
class A
{
public A(A & copy) { ... }
public static A & operator = (A & rhs) { ... }
virtual ~A() { ... }
}
class B : A { } // inherits A's destructor via virtual table