You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Boost.Asio环境下调用shared_from_this触发bad weak ptr异常求解决方案

哥们,我之前在Boost.Asio项目里踩过一模一样的坑!明明对象已经被shared_ptr拿着,调用shared_from_this()还是炸bad_weak_ptr,给你几个实际排查的方向,按顺序查大概率能找到问题:

  • 先查调用时机是不是在构造函数里
    这是最常见的坑!哪怕你的对象最终会被shared_ptr持有,但在构造函数执行期间enable_shared_from_this内部的weak_ptr还没被绑定到shared_ptr上,这时候直接或者间接(比如构造里启动异步回调,回调里调用shared_from_this)调用都会抛异常。
    比如这种错误写法:

    Node::Node(boost::asio::io_context& io) : io_(io) {
        // 作死:构造中触发异步操作,回调里用shared_from_this
        boost::asio::post(io_, [self = shared_from_this()]() {
            // ...
        });
    }
    

    解决办法是把异步启动逻辑抽成单独的start()方法,等对象被shared_ptr持有后再调用:

    auto node_ptr = std::make_shared<Node>(io);
    node_ptr->start(); // 这里再启动异步操作就安全了
    
  • 检查是不是有多个独立的shared_ptr在管理同一个对象
    enable_shared_from_this要求对象只能被一条shared_ptr链管理,如果你手动用new创建对象后,同时赋值给两个不同的shared_ptr,或者直接写shared_ptr<Node>(this)(绝对禁止!),会导致内部weak_ptr和其中一个shared_ptr不同步,后续调用shared_from_this()必然失败。
    错误示例:

    Node* raw_node = new Node(io);
    std::shared_ptr<Node> ptr1(raw_node);
    std::shared_ptr<Node> ptr2(raw_node); // 两个完全独立的shared_ptr,直接破坏引用计数
    

    正确的做法是始终用std::make_shared创建对象,或者从已有的shared_ptr派生新的智能指针。

  • 排查是不是对象已经被销毁后才触发的回调
    Boost.Asio的异步操作经常有延迟,如果你没把shared_from_this()绑定到回调里,对象的shared_ptr计数可能提前降到0导致析构,等异步回调触发时调用shared_from_this()就会炸。
    另外要记得在对象析构时取消所有未完成的异步操作,比如用boost::asio::socket::cancel()或者strand来管理任务生命周期,避免回调“复活”已销毁的对象。

  • 检查enable_shared_from_this的继承是否正确
    必须确保你的Node类是public继承boost::enable_shared_from_this<Node>,而且模板参数必须是当前类本身。如果是私有继承,或者模板参数写成了基类(比如enable_shared_from_this<Base>而Node是派生类),内部的weak_ptr根本无法正确绑定到shared_ptr上。
    正确写法:

    class Node : public boost::enable_shared_from_this<Node> {
        // ... 类成员
    };
    
  • 多线程环境下查竞态条件
    如果多个线程同时操作Node的shared_ptr,比如一个线程正在释放shared_ptr(计数到0,对象析构),另一个线程刚好调用shared_from_this(),就会出现竞态。这种情况要把所有访问Node的异步操作都放到同一个boost::asio::strand里,或者用互斥锁保护shared_ptr的访问,确保对象的生命周期操作是线程安全的。

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

火山引擎 最新活动