使用Boost ASIO通道实现协程取消时出现段错误求助
问题分析与修复
核心问题:通道生命周期导致的悬空引用
coroutine_manager中创建的通道ch是局部shared_ptr,当co_await (to_be_cancelled(*ch, io_ctx) && send_one_message(*ch))完成时(比如send_one_message先执行完毕),coroutine_manager协程结束,ch的引用计数归零被销毁。但此时to_be_cancelled协程仍持有通道的引用end,访问已销毁的通道对象会触发段错误。
其他潜在问题
send_one_message协程未co_awaitasync_send的结果,导致协程提前退出,可能引发未定义行为。- 代码中混用
io_service和io_context(两者是别名,但统一使用新的io_context更规范)。
修复后的代码
#include <boost/asio.hpp> #include <boost/asio/experimental/concurrent_channel.hpp> #include <memory> #include <iostream> #include <string> using namespace boost::asio; using namespace std; awaitable<void> to_be_cancelled( shared_ptr<experimental::concurrent_channel<void(system::error_code, string)>> end, shared_ptr<io_context> io_ctx) { ip::tcp::socket sock(*io_ctx); ip::tcp::endpoint endpoint(ip::tcp::v4(), 8000); ip::tcp::acceptor acceptor(*io_ctx, endpoint); co_await ( end->async_receive(use_awaitable_t()) || acceptor.async_accept(sock, use_awaitable_t()) ); cout << "done\n"; } awaitable<void> send_one_message( shared_ptr<experimental::concurrent_channel<void(system::error_code, string)>> channel) { co_await channel->async_send(system::error_code{}, string("hello"), use_awaitable_t()); } awaitable<void> coroutine_manager(shared_ptr<io_context> io_ctx) { auto ch = make_shared<experimental::concurrent_channel<void(system::error_code, string)>>(*io_ctx, 5); // 用shared_ptr传递通道,延长其生命周期至所有使用它的协程结束 co_await (to_be_cancelled(ch, io_ctx) && send_one_message(ch)); } int main() { auto io_ctx = make_shared<io_context>(2); co_spawn(*io_ctx, coroutine_manager(io_ctx), detached); io_ctx->run(); }
修复要点
- 将通道的传递从引用改为shared_ptr,确保所有使用通道的协程都持有共享所有权,直到协程全部结束,避免悬空引用。
- 在
send_one_message中添加co_await,等待async_send操作完成,保证协程行为的确定性。 - 统一使用
io_context替代混用的io_service,代码更规范。
内容的提问来源于stack exchange,提问作者kasra
相关产品推荐
相关产品推荐

