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

传递含派生类的unique_ptr引发SEGFAULT(段错误)原因咨询

为什么这段代码调用foo()会触发段错误?

问题核心是悬空引用结合unique_ptr的隐式转换导致的未定义行为,拆解如下:

  • 首先看main中的关键操作:

    std::unique_ptr<B> object = std::make_unique<B>();
    D d(std::move(object));
    

    std::move(object)将unique_ptr<B>转为右值,传递给D的构造函数。

  • D的构造函数参数是const std::unique_ptr<A>& arg,由于B继承自多态基类A,unique_ptr<B>可以隐式转换为unique_ptr<A>——这个转换过程会生成一个临时的unique_ptr<A>对象,它会接管原unique_ptr<B>对B对象的所有权。

  • D的成员object是const std::unique_ptr<A>&,它绑定到了这个临时对象上,但临时对象的生命周期只持续到构造函数执行结束。构造完成后,临时unique_ptr<A>被销毁,同时会释放它持有的B对象(这里还隐藏一个问题:A类没有声明虚析构函数,直接delete A*会导致B的析构函数无法被正确调用,属于额外的未定义行为)。

  • 当调用d.foo()时,object->function()试图通过这个悬空引用访问已经被销毁的unique_ptr<A>,这种未定义行为直接表现为段错误。

为什么改成存储B类的unique_ptr就正常?

如果把D的成员从const std::unique_ptr<A>&改为std::unique_ptr<B>(值类型,而非引用),构造函数改为接收std::unique_ptr<B>并转移所有权:

class D
{
public:
    D(std::unique_ptr<B> arg): object(std::move(arg)) {}
    void foo() { object->function(); }
private:
    std::unique_ptr<B> object;
};

此时D的object持有B对象的有效所有权,调用function()时自然能正常访问对象,不会出现悬空引用问题。

另外补充:多态基类(如A)必须声明虚析构函数,否则通过基类指针/智能指针销毁派生类对象时,会导致派生类的析构逻辑无法执行,引发内存泄漏或其他未定义行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 03:21:03