Asio co_composed的Lambda能否安全捕获this指针?
C++20协程Lambda与Boost.Asio co_composed的生命周期安全分析
mf1写法的安全性分析
- mf1的Lambda未捕获任何变量,通过
async_initiate传递的std::ref(*this)作为foo& self参数传入协程逻辑。 - Boost.Asio的
co_composed会将该引用参数存入协程状态中。在当前测试代码中,使用asio::deferred作为CompletionToken时,协程会同步执行,foo对象f的生命周期完全覆盖协程执行周期,访问self.val_是安全的。 - 即使后续改用异步CompletionToken(如直接投递到io_context执行),只要保证
foo对象在协程完成前持续存活,该引用就不会失效,因此这种写法本质上是安全的——它明确传递了对象依赖,更便于开发者关注生命周期管理。
mf2写法的安全性分析
- mf2的Lambda捕获了
this指针,协程状态会保存该指针的拷贝。 - 在当前测试代码中,
co_await f.mf2(asio::deferred)同步执行,foo对象f的生命周期覆盖协程执行,此时访问val_是安全的。但如果在Lambda中加入co_await导致协程挂起,同时foo对象的生命周期在挂起期间结束(比如f是动态分配后被提前释放,或是局部变量所在作用域提前退出),那么this就会变成悬空指针,后续访问val_将触发未定义行为。 - 这种写法的风险在于:
this的捕获相对隐蔽,容易让开发者忽略协程挂起期间的对象生命周期管理,当场景扩展为异步执行时,就可能出现安全问题。
总结
- mf1的写法更安全,它通过显式传递引用的方式明确依赖关系,便于开发者管控对象生命周期。
- mf2的写法在同步场景下暂时安全,但存在潜在的悬空指针风险,当协程存在挂起且对象生命周期无法保证覆盖协程全程时,这种写法是不安全的。
内容的提问来源于stack exchange,提问作者Takatoshi Kondo
相关产品推荐
相关产品推荐

