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

销毁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();
    }
}

问题分析

崩溃根源是悬空引用+对象生命周期不匹配:

  1. 线程lambda中捕获的ioService_是类成员引用,一旦IoServiceThreadGuard被销毁,该引用可能指向已释放的io_service对象;
  2. 析构函数先调用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 09:14:58