使用unique_ptr与多态时的内存泄漏问题及重构建议
多态场景下unique_ptr内存泄漏的解决方案
你的代码不存在循环依赖,但Valgrind检测到的4字节泄漏确实是SecondChild未被销毁导致的,核心问题是基类Parent没有声明虚析构函数。
当std::unique_ptr<Parent>指向派生类Child对象时,销毁这个智能指针只会调用Parent的析构函数,不会触发Child的析构逻辑。这就导致Child中的content成员(持有SecondChild的unique_ptr)无法被自动释放,最终造成SecondChild的内存泄漏。
修复方案(无需修改Child中的std::unique_ptr<Parent>)
只需要给Parent类添加虚析构函数,让多态析构生效:
#include <iostream> #include <memory> using namespace std; struct Parent { Parent() { cout << "Expr created" << endl; } // 添加virtual关键字,将析构函数变为虚函数 virtual ~Parent() { cout << "Expr destroyed" << endl; } }; struct Child : public Parent { std::unique_ptr<Parent> content; }; struct SecondChild : public Parent { int val; }; std::unique_ptr<Parent> foo() { auto test = make_unique<Child>(); auto content_in_child = make_unique<SecondChild>(); content_in_child->val = 4; test->content = std::move(content_in_child); return test; } int main() { std::unique_ptr<Parent> high = foo(); return 0; }
修复原理
C++中,基类的析构函数如果是虚函数,那么通过基类指针/智能指针销毁派生类对象时,会按照派生类→基类的顺序调用析构函数。修改后:
- 销毁
high时,会先调用Child的析构函数(编译器通过虚函数表找到正确的析构逻辑) Child的析构函数会自动销毁其成员content,进而调用SecondChild的析构函数- 最终所有对象的内存都会被正确释放,Valgrind不会再检测到泄漏
内容的提问来源于stack exchange,提问作者user20158758
相关产品推荐
相关产品推荐

