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




