boost::asio类成员初始化strand时因新增io_context崩溃
新增io_context并初始化strand时崩溃问题排查与解决
问题场景
在包含io_context和strand的类中,尝试新增一个独立的io_context成员,并为其绑定对应的strand时,程序出现崩溃。现有io_context通过构造函数传入引用。
类成员定义
boost::asio::io_context& io_context_; boost::asio::io_context io_context_2; boost::asio::strand<boost::asio::io_context::executor_type> strand_; boost::asio::strand<boost::asio::io_context::executor_type> strand_2;
崩溃版本构造函数
Server( boost::asio::io_context& ioc ) : io_context_(ioc), io_context_2(), strand_(io_context_.get_executor()), strand_2(io_context_2.get_executor()) { }
测试现象
- 即使将
strand_2绑定到传入的io_context_(而非新增的io_context_2),只要保留io_context_2的初始化,程序依然崩溃 - 注释掉初始化列表中的
io_context_2()后,程序可正常运行:
Server( boost::asio::io_context& ioc ) : io_context_(ioc), // io_context_2(), strand_(io_context_.get_executor()), strand_2(io_context_.get_executor()) { }
崩溃错误信息
Unhandled exception at 0x00007FFC8BD7FAAD (ntdll.dll) in server.exe.9124.dmp: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
错误触发于win_mutex.hpp的win_mutex::lock函数中。
原因分析
问题大概率与对象初始化时机或Boost.Asio内部实现细节有关:
- 虽然初始化列表顺序与类成员声明顺序一致,但
io_context_2的默认构造可能未完全完成内部资源初始化,就被strand_2调用get_executor()获取执行器,导致访问无效的同步原语(如未初始化的mutex)。 - 旧版本Boost.Asio在Windows平台下,多
io_context实例初始化可能存在资源竞争或内部初始化bug。 - 原代码中构造函数参数列表后多余的逗号,可能导致编译后生成的代码存在未定义行为。
解决方案
方案1:在构造函数体内初始化strand_2
推迟strand_2的初始化到构造函数体内,确保io_context_2完全完成构造:
Server(boost::asio::io_context& ioc) : io_context_(ioc), io_context_2(), strand_(io_context_.get_executor()) { // 构造函数体内初始化,确保io_context_2已完全就绪 strand_2 = boost::asio::strand<boost::asio::io_context::executor_type>(io_context_2.get_executor()); }
方案2:显式指定io_context的线程池大小
初始化io_context_2时显式传入线程数参数,避免默认构造的潜在问题:
Server(boost::asio::io_context& ioc) : io_context_(ioc), io_context_2(1), // 指定线程池大小为1 strand_(io_context_.get_executor()), strand_2(io_context_2.get_executor()) { }
方案3:升级Boost版本
如果使用的是较旧的Boost库,尝试升级到最新稳定版本,修复可能存在的平台特定bug。
方案4:检查并修正语法错误
确保构造函数参数列表没有多余逗号,避免未定义行为:
// 修正后的参数列表 Server(boost::asio::io_context& ioc) : ... // 初始化列表 { }
内容的提问来源于stack exchange,提问作者NabaMan
相关产品推荐
相关产品推荐

