C ++ memory is not freed when a pointer to a subclass is deleted

I use dynamic memory allocation in my code, and I'm having trouble trying to remove a pointer to a subclass. I found that the initially allocated memory is not freed when I use the delete keyword. Functionality works great with the original base class.

This is a problem because I run the code on arduino, and RAM quickly eats up and then crashes.

Here is a sample 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 assume this has something to do with the destructor syntax in the base class. Even if I create a custom destructor for a subclass, the same problems occur.

Any ideas?

+4
source share
5 answers

In C ++, constructors are called up in the hierarchy , i.e. when creating Derived , Base() is executed before Derived() . This means that you are running objPtr = new SomeObject; twice and only once delete it.

You should also make your base class destructor virtual, especially if you ever remove Derived instances from Base ptr.

+5
source

You must make a virtual virtual base class descriptor.

 virtual ~Base(){ delete objPtr; } 
+3
source

The Sub :: Sub () constructor allocates a second optional SomeObject after the first has been allocated by the Base :: Base () superconstructor and the second assigned pointer has been assigned objPtr, causing the leak.

Note: Base :: Base () is implicitly called Sub :: Sub ()

Solution: just remove the unnecessary selection in Sub :: Sub ()

Another suggestion: make your base destructor virtual, as recommended with inheritance

 virtual ~Base(){ delete objPtr; } 
+1
source

When you create a derived class, it first calls the constructor of the Base class, and then the Sub constructor, you can see it 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 a second time in Sub . Then the memory allocated in Base is lost and you have a leak. You also need to make a virtual destructor to work correctly with derived classes.

0
source

The memory for this pointer is allocated twice. That way, you will never free all the memory that you are new to. Just make the pointer a private member and select it only in the base class.

0
source

All Articles