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

关于从原始指针创建shared_ptr时文档描述与实际冲突的疑问

关于shared_ptr从原始指针创建导致双重释放的疑问

微软官方文档提到,从原始指针创建新的shared_ptr时,该新shared_ptr与原实例独立且不控制底层资源,但实际编写的代码却出现了双重释放错误,Stack Overflow相关案例也显示这种操作会导致资源被两次删除,因此对文档描述的含义存在疑问。

测试代码

void f(int* ptr)
{
    shared_ptr<int> sptr(ptr);
    cout << "sptr in f: " << sptr.get() << endl;
}

int main()
{
    auto sp1 = make_shared<int>(1);
    cout << "sp1 in main: " << sp1.get() << endl;
    f(sp1.get());
    return 0;
}

错误输出

sp1 in main: 0x6000016f5138
sptr in f: 0x6000016f5138
a.out(12083,0x119097600) malloc: *** error for object 0x6000016f5138: pointer being freed was not allocated
a.out(12083,0x119097600) malloc: *** set a breakpoint in malloc_error_break to debug
zsh: abort      ./a.out

问题解析与解决

错误原因

微软文档的描述有隐藏前提,容易造成误解。正确逻辑是:

  • 如果原始指针没有被任何智能指针管理,用它创建shared_ptr时,新的shared_ptr会接管资源控制权;
  • 但如果原始指针已经被另一个shared_ptr(比如示例里的sp1)管理,此时再用这个指针创建新的shared_ptr,两个shared_ptr会各自维护独立的引用计数,互相不知道对方的存在。

示例里,sp1和sptr都认为自己是这块内存的唯一管理者:函数f结束时sptr销毁,释放一次内存;main函数结束时sp1销毁,又尝试释放同一块内存,直接触发双重释放错误。

正确写法

要传递shared_ptr的共享所有权,直接传shared_ptr对象即可,这样引用计数会同步增加:

void f(shared_ptr<int> sptr)
{
    cout << "sptr in f: " << sptr.get() << endl;
}

int main()
{
    auto sp1 = make_shared<int>(1);
    cout << "sp1 in main: " << sp1.get() << endl;
    f(sp1);
    return 0;
}

这样所有共享的shared_ptr会共用同一个引用计数,只有当最后一个shared_ptr销毁时,才会释放底层资源,不会出现重复释放的问题。

对微软文档的澄清

微软文档说的“新shared_ptr与原实例独立且不控制底层资源”,应该是指原始指针未被智能指针管理的场景——此时不存在“原智能指针实例”,新shared_ptr自然和不存在的实例独立,并且接管原本无主的资源。文档没明确强调这个前提,才导致了误解。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 02:24:28