销毁boost::asio::io_service时发生崩溃,请求排查代码问题
Boost.Asio销毁io_service时崩溃问题排查
我在使用boost::asio时遇到销毁io_service时崩溃的问题,以下是回溯信息和相关代码,请帮忙排查。
回溯信息
(gdb) bt #0 boost::asio::detail::scheduler::work_finished (this=this@entry=0x0) at /ephemeral/workspace/CB.SBTS_PSINT2.FLOW/build/build/sm6-snowfish-nrt/tmp/work/tremont-64-pc-linux-gnu/sysadapt/67c8d51ea9241fcd4ff1b192870be178f5a70540-r1/recipe-sysroot/usr/include/c++/10.2.0/bits/atomic_base.h:333 #1 0x0000000000785fe6 in boost::asio::io_context::work::~work (this=<synthetic pointer>, __in_chrg=<optimized out>) at /ephemeral/workspace/CB.SBTS_PSINT2.FLOW/build/build/sm6-snowfish-nrt/tmp/work/tremont-64-pc-linux-gnu/sysadapt/67c8d51ea9241fcd4ff1b192870be178f5a70540-r1/recipe-sysroot/usr/include/boost/asio/impl/io_context.hpp:427 #2 common::IoServiceThreadGuard::IoServiceThreadGuard(boost::asio::io_context&, unsigned int)::{lambda()#1}::operator()() const (__closure=<optimized out>)
相关代码
explicit IoServiceThreadGuard(boost::asio::io_service& ioService, unsigned int count) : ioService_{ioService}, threadCount_(count) { for (unsigned int i = 0; i < threadCount_; ++i) { threads_.create_thread( [&]() { boost::asio::io_service::work work(ioService_); ioService_.run(); }); // NOLINT } } ~IoServiceThreadGuard() { try { if (not ioService_.stopped()) { ioService_.stop(); } threads_.join_all(); } catch (const std::exception& e) { logger << ::info << "~IoServiceThreadGuard() throw error: " << e.what(); } }
问题分析
崩溃根源是悬空引用+对象生命周期不匹配:
- 线程lambda中捕获的
ioService_是类成员引用,一旦IoServiceThreadGuard被销毁,该引用可能指向已释放的io_service对象; - 析构函数先调用
ioService_.stop()强制终止run(),此时线程栈上的work对象才开始析构。如果此时io_service已经被销毁,work的析构函数调用work_finished时就会访问失效的scheduler指针(即回溯中的this=0x0),触发崩溃。
修复方案
调整对象生命周期管理和析构逻辑,确保所有操作都在有效对象上执行:
#include <boost/asio.hpp> #include <boost/thread.hpp> #include <boost/optional.hpp> class IoServiceThreadGuard { public: explicit IoServiceThreadGuard(boost::asio::io_service& ioService, unsigned int count) : ioService_(ioService), threadCount_(count), work_(ioService_) // 将work作为类成员,维持io_service的运行状态 { for (unsigned int i = 0; i < threadCount_; ++i) { threads_.create_thread( [this]() // 捕获this避免引用悬空 { ioService_.run(); }); } } ~IoServiceThreadGuard() { try { // 先销毁work对象,让io_service在完成剩余任务后自然退出 work_.reset(); // 等待所有工作线程执行完毕 threads_.join_all(); } catch (const std::exception& e) { logger << ::info << "~IoServiceThreadGuard() throw error: " << e.what(); } } private: boost::asio::io_service& ioService_; unsigned int threadCount_; boost::thread_group threads_; // 使用optional控制work的销毁时机 boost::optional<boost::asio::io_service::work> work_; };
关键修改点
- 将
work从线程栈变量改为类成员,用boost::optional控制其销毁时机,确保在析构时主动触发io_service的工作计数减少; - 线程lambda捕获
this而非直接引用,避免引用悬空问题; - 析构时先销毁
work,让io_service的run()自然退出,而非强制调用stop(),避免work析构时访问已失效的io_service对象。
额外注意事项
必须保证io_service对象的生命周期严格长于IoServiceThreadGuard和所有工作线程,否则仍会出现悬空引用问题。如果确实需要强制终止任务,调用stop()后也必须等待所有线程完全退出,再销毁io_service。
内容的提问来源于stack exchange,提问作者merkey
相关产品推荐
相关产品推荐

