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

使用unique_ptr的reset方法触发free(): invalid pointer错误,make_unique则正常的问题咨询

使用unique_ptr的reset方法触发free(): invalid pointer错误,make_unique则正常的问题咨询

嘿,咱们来拆解下你遇到的这个问题,核心是unique_ptr的管理规则和你传入的指针类型不匹配导致的,先看你的完整代码:

#include <iostream>
#include <memory>
#include <string>

using namespace std;

int main() {
    unique_ptr<string> p= nullptr;

    auto l=[&p]()->void{
        static string x {"1111"};
        cout<<x<<endl;
        //p = std::make_unique<string>(x);// compile ok
        p.reset(&x);//compile error free():invalid pointer;
        cout<<p.get()<<endl;
        return;
    };

    l();
    cout<<p->length()<<endl;
    cout<<p.get()<<endl;
    return 0;
}

问题根源分析

先对比两种写法的本质差异:

  • std::make_unique<string>(x)为什么正常?
    这个函数会在堆内存上新建一个string对象,把静态变量x的值拷贝到这个新对象里,然后让unique_ptr接管这个堆对象的所有权。unique_ptr的默认删除器是用delete释放内存,而堆内存正是通过new分配的,完全符合它的管理规则,所以销毁时不会出问题。

  • p.reset(&x)为什么触发错误?
    你传给reset的是静态变量x的地址,x是static修饰的局部变量,它存储在静态存储区,根本不是通过new动态分配的堆内存。而unique_ptr的默认行为是在生命周期结束时调用delete来释放它管理的指针,但delete只能用于释放new分配的堆内存,对静态存储的对象执行delete是完全非法的未定义行为,这就是你看到free(): invalid pointer错误的直接原因。

关于你的猜想的补充

你提到“离开作用域时析构函数被调用两次”,其实准确的逻辑是:
静态变量x的生命周期是整个程序,程序结束时它会被自动销毁(这是正常行为);而unique_ptr在main函数结束时销毁,会尝试用delete释放x的地址,这相当于对同一个静态对象执行了一次非法的内存释放操作,并不是析构函数被调用两次,但这个非法操作已经足够触发内存错误了。

怎么解决?

如果确实需要让unique_ptr管理这个静态对象,你需要给它指定一个空删除器,告诉它不需要释放内存:

p.reset(&x, [](string*){}); // 自定义删除器,什么都不做

不过更建议的方式是:静态变量本身不需要智能指针来管理,直接使用即可,unique_ptr的设计初衷就是用来管理动态分配的堆内存,别让它越界干活~

备注:内容来源于stack exchange,提问作者Paoer111

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 11:53:13