Why does a string in a C ++ subclass cause a memory leak?

I spent more than 2 hours searching for this memory leak:

class Parent{ ... } class Child:public Parent{ std::string str; ... } int main(){ Parent *ptr=new Child(); delete ptr; } 

I fixed this by moving the string to the parent class. Why did a memory leak occur? Should not child members be deleted?

+5
source share
1 answer

This can happen because Parent may not have a virtual destructor. Since you are creating Parent* (the base class) for the dynamically distributed child derived class, removing Parent* , which does not have a virtual destructor, will lead to undefined behavior, but usually will cause the derived class to not be destroyed.

From Scott Myers - Effective C ++ 3rd Edition :

... if we remove the base class pointer with a non-virtual destructor, the results will be undefined. What usually happens at runtime is that the derived part of the object is never destroyed. This is a great way to leak resources, damaged data structures, and spend a lot of time with the debugger. Thus, any class with virtual functions should have an almost virtual destructor.

 class Parent{ }; class Child:public Parent{ public: Child() : str("Child") {} ~Child() { std::cout << str << std::endl;}; std::string str; }; int main(){ Parent *ptr=new Child(); delete ptr; // undefined behaviour: deleting a Base* to a Derived object where the Base has no virtual destructor } 

You can fix this by creating a Parent virtual destructor:

 class Parent{ public: virtual ~Parent() {} // Will call derived classes destructors now as well }; class Child:public Parent{ public: Child() : str("Child") {} ~Child() { std::cout << str << std::endl;}; std::string str; }; int main(){ Parent *ptr=new Child(); delete ptr; // Child::~Child() has now been called. } 

See When to use virtual destructors? who probably explain it better than I did

Change Thanks to @aschepler (in the comments for comments), the commentators below and the answer to the related question, I updated the answer to better understand that this is undefined behavior. In my haste, I didn’t mention this and only mentioned typical behavior

+11
source

All Articles