You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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++中,基类的析构函数如果是虚函数,那么通过基类指针/智能指针销毁派生类对象时,会按照派生类→基类的顺序调用析构函数。修改后:

  1. 销毁high时,会先调用Child的析构函数(编译器通过虚函数表找到正确的析构逻辑)
  2. Child的析构函数会自动销毁其成员content,进而调用SecondChild的析构函数
  3. 最终所有对象的内存都会被正确释放,Valgrind不会再检测到泄漏

内容的提问来源于stack exchange,提问作者user20158758

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 00:05:06