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

带自定义删除器的unique_ptr以nullptr初始化后修改原始指针的疑问

unique_ptr提前绑定未初始化指针导致资源泄漏的原因

在与管理指针创建/销毁的C库交互场景中,若在原始指针指向有效内存前就用unique_ptr接管它,会导致资源泄漏,删除器无法被正确调用。以下是模拟该错误场景的代码:

#include <memory>
#include <iostream>
struct Foo {
  std::string s;
};
// 模拟使用输出指针的C库函数
void init_foo(Foo** foo_ptr_ptr) {
    std::cout << "Initializing Foo\n"; 
    Foo* f = new Foo; 
    *foo_ptr_ptr = f;
};
// 通过C API实现的自定义资源销毁函数
void delete_foo(Foo* foo) {
    std::cout << "Invoking destructor!\n";
  if (foo != nullptr) {
    std::cout << "Deleting Foo\n";
    delete foo;
  } 
}

int main() {
    Foo * foo {nullptr};
    // 错误:先创建unique_ptr,此时它接管的是nullptr
    std::unique_ptr<Foo, decltype(&delete_foo)> foo_ptr {foo, &delete_foo};
    init_foo(&foo); // 修改的是外部原始指针,unique_ptr对此不知情
    return 0;
}

问题本质

  • unique_ptr构造时会拷贝传入的指针值(此处是nullptr)并保存为内部管理的指针,后续它只会基于这个内部指针执行销毁逻辑。
  • 调用init_foo(&foo)修改的是独立的foo指针变量,而非unique_ptr内部存储的指针。unique_ptr完全不知道外部有新的资源被分配,因此析构时只会对初始的nullptr调用删除器——而delete_foo对nullptr不做任何实际释放操作,最终导致init_foo分配的Foo对象永远泄漏。
  • 这种操作不属于C++标准定义的未定义行为,只是违反了unique_ptr的使用规则:它应当接管已经指向有效资源的指针,且接管后外部不得再手动修改或管理该资源的指针。

正确实现方式

必须先通过C API初始化原始指针,确保它指向有效资源后,再交给unique_ptr接管:

int main() {
    Foo * foo {nullptr};
    init_foo(&foo); // 先初始化指针,获取有效资源
    std::unique_ptr<Foo, decltype(&delete_foo)> foo_ptr {foo, &delete_foo}; // 由unique_ptr接管资源
    return 0;
}

此时unique_ptr内部保存的是指向有效Foo对象的指针,析构时会调用delete_foo正确释放资源,避免泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 22:24:33