shared_ptr表现与教材不符,求解释双free异常成因
哥们,你这个问题完全是踩了std::shared_ptr最经典的坑之一——错误地用裸指针(通过get()获取)构造新的shared_ptr,直接破坏了它的引用计数核心机制!
先拆解你的代码问题出在哪
我们一步步走一遍代码的执行逻辑:
- 第一行
std::shared_ptr<A> ptr(new A(12));:ptr成功接管了new A(12)的内存,此时引用计数为1。 - 内部作用域里
std::shared_ptr<A> ptr1 = ptr;:这是正确的shared_ptr复制操作,引用计数会增加到2;当作用域结束ptr1销毁,引用计数又回到1,这步完全没问题,不会触发析构。 - 致命错误在这里:
std::shared_ptr<A> ptr2(ptr.get());get()只是返回shared_ptr管理的裸指针,但不会传递任何引用计数信息。- 用这个裸指针构造新的
ptr2时,ptr2会新建一个独立的引用计数,初始值为1——它完全不知道ptr已经在管理同一块内存!
现在内存里有两个互不知情的shared_ptr:ptr的引用计数是1,ptr2的引用计数也是1,它们指向同一块堆内存。
为什么会触发双free?
当程序执行到main函数末尾,局部变量会按逆序销毁:
- 先销毁
ptr2:它的引用计数减到0,于是调用~A()释放内存,控制台输出第一个dis A。 - 接着销毁
ptr:它的引用计数也减到0,又一次调用~A(),并尝试释放已经被ptr2释放过的内存——这就是典型的double free错误,直接触发了系统的内存保护机制。
你的理解误区
你对shared_ptr的核心逻辑(最后一个指针销毁才释放资源)的理解是对的,但忽略了一个关键前提:只有通过shared_ptr自身的复制/移动构造、赋值操作,才能让多个指针共享同一个引用计数。用裸指针构造新的shared_ptr,相当于给同一块内存分配了两套独立的“管理系统”,它们各自为政,最终必然导致重复释放。
修复方法
把std::shared_ptr<A> ptr2(ptr.get());改成以下任意一种正确的方式:
std::shared_ptr<A> ptr2 = ptr;(复制赋值)std::shared_ptr<A> ptr2(ptr);(复制构造)
这样ptr2会和ptr共享同一个引用计数,此时引用计数会变成2;当程序结束时,两个指针依次销毁,引用计数降到0时才会调用一次~A(),彻底避免双free问题。
修复后的输出应该是:
cons A Inside Scope Outside Scope dis A
内容的提问来源于stack exchange,提问作者Umar Farooq
相关产品推荐
相关产品推荐

