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

为何用make_shared创建对象仍触发std::bad_weak_ptr异常?

问题根由 & 解决办法

为啥会抛std::bad_weak_ptr?

哪怕你用std::make_shared创建对象,只要在构造函数里调用shared_from_this(),必然会触发这个异常——因为make_shared的执行顺序是:先分配内存、构造对象,之后才会初始化enable_shared_from_this内部的weak_ptr。构造函数运行时,这个weak_ptr还是空的,调用shared_from_this()自然会报错。

另一种可能是对象已经被析构后再调用shared_from_this(),但结合你用make_shared的场景,大概率是第一种情况导致的。

怎么解决?

1. 把异步启动逻辑从构造函数里拆出来

别在构造函数里提交异步任务,单独写一个start()方法,等对象被shared_ptr持有之后再调用这个方法:

class MyAsyncObj : public std::enable_shared_from_this<MyAsyncObj> {
public:
    // 构造函数只做基础初始化,绝不碰异步操作
    MyAsyncObj(boost::asio::io_context& io_ctx) : io_ctx_(io_ctx) {}

    // 专门的启动方法,此时对象已经被shared_ptr持有
    void start() {
        auto self = shared_from_this(); // 这里调用绝对安全
        io_ctx_.post([self]() {
            self->doAsyncStuff();
        });
    }

private:
    void doAsyncStuff() {
        // 后续异步操作继续用shared_from_this()获取自身引用,保证对象不被提前析构
        auto self = shared_from_this();
        io_ctx_.post([self]() {
            // 你的业务逻辑...
        });
    }

    boost::asio::io_context& io_ctx_;
};

// 调用方式
auto obj = std::make_shared<MyAsyncObj>(io_ctx);
obj->start(); // 必须等shared_ptr创建完成后再调用start

2. 所有异步回调必须持有shared_ptr

不管是什么异步任务,只要提交到io_context,回调里一定要捕获shared_from_this()拿到的self。这样只要有未完成的异步任务,对象就会被shared_ptr持有,不会被析构;等所有回调执行完毕,没有shared_ptr持有它时,对象会自动销毁,完全符合你的需求。

和Boost.Beast示例的差异

Boost.Beast的示例(比如HTTP服务端/客户端)全都是先创建shared_ptr对象,再启动异步流程的设计:

  • 构造函数只初始化套接字、上下文这类资源,绝不触发异步操作
  • 调用start()或者run()这类方法时,才通过shared_from_this()获取自身引用提交任务
  • 所有异步回调都会捕获shared_ptr,把对象的生命周期和异步任务绑定在一起

这种设计从根源上避免了构造函数里调用shared_from_this()的坑,这就是你能正常运行Beast示例但自己代码出问题的核心原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 07:40:30