调用shared_from_this()触发std::bad_weak_ptr异常的排查求助
我来帮你捋捋这个问题——你遇到的std::bad_weak_ptr异常,哪怕确认不是在构造阶段调用shared_from_this(),也大概率是对象的智能指针管理出了隐形问题,结合你的场景,我给你列几个最可能的排查方向:
1. 先确认worker_thread的继承方式是否正确
std::enable_shared_from_this必须是public继承,如果你的worker_thread是private/protected继承它,内部的weak_ptr初始化逻辑会失效。检查你的类定义是不是写成了这样:
// 错误写法:缺少public关键字 class worker_thread : std::enable_shared_from_this<worker_thread> { ... }; // 正确写法 class worker_thread : public std::enable_shared_from_this<worker_thread> { ... };
这是最容易忽略的细节,非public继承会导致shared_from_this()无法正确访问基类的weak_ptr成员,直接触发异常。
2. 排查是否存在"重复管理"同一个对象的shared_ptr
有没有可能在某个地方,用worker_thread的裸指针手动创建了另一个shared_ptr?比如有人写了:
// 致命错误!这会让两个独立的shared_ptr管理同一个对象 std::shared_ptr<worker_thread> bad_ptr(this);
这种情况会导致:当其中一个shared_ptr被销毁时,对象内存被释放,剩下的shared_ptr内部的weak_ptr就会失效,此时调用shared_from_this()必然抛出bad_weak_ptr。
解决办法:确保所有worker_thread实例都只通过std::make_shared创建,并且所有传递都依赖已有的shared_ptr(比如用shared_from_this()或者直接传容器里的shared_ptr),绝对不能用裸指针新建shared_ptr。
3. 确认connection_manager里的shared_ptr是否真的"存活"
虽然你说connection_manager持有所有worker_thread的shared_ptr,但要排查:
- 调用
get_available_connection()时,对应的worker_thread的shared_ptr是不是已经被从容器中erase或者reset了?比如有没有线程在动态销毁worker,刚好和你调用的时机产生竞态? - 可以给worker_thread加构造/析构日志,看看调用
shared_from_this()时,对象是不是已经进入析构流程了?
4. 多线程环境下的竞态条件要重点排查
你的服务端是多线程架构,很可能出现:
- 线程A正在调用
worker->get_available_connection(),执行到shared_from_this()的瞬间 - 线程B刚好在connection_manager里reset了这个worker的shared_ptr,导致对象的weak_ptr被置空
这种情况下shared_from_this()内部的weak_ptr::lock()会失败,抛出异常。解决办法是给worker的访问加同步保护:比如在connection_manager的get_available_connection()调用前后加互斥锁,确保对象生命周期不会在操作中途被截断。
最后给你个代码检查示例
假设你的核心代码类似这样,重点标记需要确认的点:
// 必须public继承enable_shared_from_this class worker_thread : public std::enable_shared_from_this<worker_thread> { public: void init() { /* ... */ } std::shared_ptr<connection> get_available_connection() { // 这里调用前,必须确保当前对象有至少一个存活的shared_ptr auto self = shared_from_this(); // 异常触发点 return std::make_shared<connection>(self); } }; class connection_manager { private: std::mutex mtx; std::vector<std::shared_ptr<worker_thread>> workers; public: void create_workers(int count) { std::lock_guard<std::mutex> lock(mtx); for (int i=0; i<count; ++i) { auto worker = std::make_shared<worker_thread>(); worker->init(); workers.push_back(worker); // 确保这里正确存储,没有遗漏 } } std::shared_ptr<connection> get_connection() { std::lock_guard<std::mutex> lock(mtx); // 确保workers[0]是有效的,没有被erase/reset return workers[0]->get_available_connection(); } };
先从继承权限和shared_ptr的唯一性排查,再检查多线程下的同步问题,基本就能定位到问题所在。
内容的提问来源于stack exchange,提问作者Petar Nikić




