c++ asio stackful协程 c++如何使用boost asio的spawn进行编程

浅晨吖_1425

浅晨吖_1425

2026-03-21

634人浏览

原创

spawn本质是stackful协程,基于boost.coroutine2实现栈上下文保存与切换,需严守void返回、yield_context参数、strand串行化、error_code显式检查及栈大小限制等规则。

c++ asio stackful协程 c++如何使用boost asio的spawn进行编程

spawn 本质是 stackful 协程,不是 async_xxx 的语法糖

很多人以为 spawn 就是把 async_read 换成 co_await 那种写法,其实完全不是。Boost.Asio 的 spawn 基于 Boost.Coroutine2(非 C++20 协程),它在栈上保存完整执行上下文,每次挂起/恢复都涉及栈拷贝和切换——这意味着不能在 spawn 启动的函数里直接用局部大对象、递归过深、或跨线程访问未同步的栈变量。

实操建议:

  • spawn 启动的函数必须是 void 返回类型,且参数只能是 yield_context 或其引用(如 boost::asio::yield_context)
  • 不要试图在 spawn 函数里捕获 std::exception_ptr 后再抛出——栈切换会破坏异常传播链,改用返回错误码或 boost::system::error_code
  • 若需传参,必须通过闭包捕获,且确保被捕获对象的生命周期覆盖整个协程运行期(常见坑:捕获局部 std::string 后协程异步延迟执行,字符串已析构)

spawn 必须搭配 io_context::strand 使用才能安全共享状态

多个 spawn 协程并发读写同一个 socket 或共享变量时,Asio 不自动加锁。因为 spawn 是协作式调度,不等同于线程,但也不保证原子性——尤其当协程在不同线程中被唤醒(比如一个 spawn 在 io_context::run() 线程,另一个在 post() 触发的线程)。

实操建议:

  • 所有对共享资源(如 std::vector<int></int> 缓存、tcp::socket 对象)的访问,必须包裹在 strand 内:用 make_strand(io_context) 构造,然后以 strand.dispatch() 或 strand.post() 调度协程启动
  • 别用 io_context::wrap() 替代 strand——它只保正回调在同一线程执行,不防重入;而 strand 提供串行化语义,这才是协程间状态安全的关键
  • socket 本身不是线程安全的,即使只在一个 spawn 里用,也要注意:如果该 socket 同时被另一个线程调用 close(),会触发未定义行为——所以关闭动作也得走同一 strand

错误处理必须显式检查 error_code,不能依赖异常

Asio 的 spawn 默认不抛异常,所有 I/O 错误都通过 boost::system::error_code& 参数返回。如果你漏掉这个参数,或者写了 error_code ec(值传递)而不是 error_code& ec(引用),就会收不到错误信息,协程静默失败。

常见错误现象:async_read 立即返回 error_code=operation_aborted,但协程继续往下跑,后续操作崩溃。

C++ Code Review Master
C++ Code Review Master

组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。

下载

实操建议:

  • 每个 Asio I/O 操作后必须立刻检查 ec,例如:async_read(socket, buf, ec); if (ec) return;
  • 不要在 spawn 函数里 try/catch —— spawn 启动的函数不支持栈展开,异常会直接 terminate
  • 若需统一错误处理,用 boost::asio::async_compose 自定义操作,而非硬塞 try/catch

协程栈大小默认 128KB,超限就 SIGSEGV,但无法 runtime 调整

Boost.Coroutine2 为每个 spawn 分配固定大小栈,默认 128KB。它不支持像 Windows Fiber 或 Linux ucontext 那样动态增长,一旦局部变量 + 调用深度超过限额,就是段错误,且堆栈信息里看不到协程痕迹,只显示 coro_invoke 地址。

性能与兼容性影响:增大栈会提高内存占用(尤其高并发时),减小则容易 crash;而且该值在编译时由 BOOST_COROUTINES_NO_DEPRECATION_WARNING 和宏 BOOST_COROUTINES_STACK_SIZE 控制,运行时不可改。

实操建议:

  • 编译前定义 -DBOOST_COROUTINES_STACK_SIZE=262144(256KB)应对复杂逻辑,但别盲目设到 1MB——Asio 协程不是为重型计算设计的
  • 避免在 spawn 函数里定义大数组(如 char buf[65536]),改用 std::vector<char>(65536)</char> 或堆分配
  • 递归调用 spawn 是危险操作,每次嵌套都吃一份栈——应改为循环 + 状态机模拟

协程栈和 strand 是最容易被跳过的两个点,但只要其中一个没对齐,程序就可能在压力下随机崩,而且复现困难。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

5959

3

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.03

1678

5

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.04

2524

5

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

2023.10.24

5964

49

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

2023.11.24

5369

6

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

2024.03.22

7074

16

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

2024.04.29

10034

11

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

2025.07.29

5099

17

c++字符串相关教程
c++字符串相关教程

本专题整合了c++字符串相关教程,阅读专题下面的文章了解更多详细内容。

2025.08.07

5447

13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习