为什么 C++ 子类中的字符串会导致内存泄漏?
Why does a string in a C++ subclass cause memory leaks?
我花了 2 个多小时才找到这个内存泄漏:
class Parent{
...
}
class Child:public Parent{
std::string str;
...
}
int main(){
Parent *ptr=new Child();
delete ptr;
}
我通过将字符串移动到 parent class 来修复它。为什么会发生这种内存泄漏? child的成员不应该也被删除吗?
之所以会发生这种情况,是因为 Parent
可能没有虚拟析构函数。由于您正在为动态分配的派生 class Child
创建 Parent*
(基础 class),因此删除没有虚拟析构函数的 Parent*
将导致未定义行为,但通常会导致派生的 class 不会被破坏。
来自Scott Myers - Effective C++ Third Edition:
... if we delete Base class pointer with a non-virtual destructor, results are undefined. What typically happens at runtime is that the derived part of the object is never destroyed. This is an excellent way to leak resources, corrupt data structures, and spend a lot of time with a debugger. So any class with virtual functions should almost certainly have a 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
}
您可以通过使 Parent
的析构函数 virtual
:
来解决这个问题
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.
}
请参阅 When to use virtual destructors?,这可能比我解释得更好
编辑:感谢@aschepler(在问题的评论中)、下面的评论者和链接问题的答案,我更新了答案以更好地反映这一点这是未定义的行为。匆忙中我没有提到它,只提到了典型行为
我花了 2 个多小时才找到这个内存泄漏:
class Parent{
...
}
class Child:public Parent{
std::string str;
...
}
int main(){
Parent *ptr=new Child();
delete ptr;
}
我通过将字符串移动到 parent class 来修复它。为什么会发生这种内存泄漏? child的成员不应该也被删除吗?
之所以会发生这种情况,是因为 Parent
可能没有虚拟析构函数。由于您正在为动态分配的派生 class Child
创建 Parent*
(基础 class),因此删除没有虚拟析构函数的 Parent*
将导致未定义行为,但通常会导致派生的 class 不会被破坏。
来自Scott Myers - Effective C++ Third Edition:
... if we delete Base class pointer with a non-virtual destructor, results are undefined. What typically happens at runtime is that the derived part of the object is never destroyed. This is an excellent way to leak resources, corrupt data structures, and spend a lot of time with a debugger. So any class with virtual functions should almost certainly have a 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
}
您可以通过使 Parent
的析构函数 virtual
:
来解决这个问题
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.
}
请参阅 When to use virtual destructors?,这可能比我解释得更好
编辑:感谢@aschepler(在问题的评论中)、下面的评论者和链接问题的答案,我更新了答案以更好地反映这一点这是未定义的行为。匆忙中我没有提到它,只提到了典型行为