std::coroutine_handle::resume() 必须在协程挂起后且句柄有效、未结束时调用,否则行为未定义;需检查 handle.address() != nullptr && !handle.done(),避免重复 resume、野指针或 noop_coroutine 后误用。

std::coroutine_handle::resume() 必须在协程挂起后调用
直接调用 resume() 前,必须确保协程已处于挂起状态(即已执行过 co_await、co_yield 或进入 final_suspend),否则行为未定义——常见表现是程序崩溃或静默跳过后续逻辑。
典型错误是:刚创建协程就立刻 resume(),而它还没走到 initial_suspend() 之后的代码;或者在 final_suspend() 返回 std::suspend_always{} 后,误以为“协程还在运行”,其实它已在结束前挂起了。
-
initial_suspend()返回std::suspend_always{}:协程创建后立即挂起,此时可安全resume() - 返回
std::suspend_never{}:协程会一路执行到第一个挂起点(如co_await)才停,此时才能恢复 - 调用
resume()前,建议先用handle.done()检查是否已结束(注意:done()为true表示不可再resume)
resume() 前必须确保 handle 有效且未被销毁
协程句柄 std::coroutine_handle<p></p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master"><img
src="https://img.php.cn/upload/skill/000/000/081/179051228971575.jpg" alt="C++ Code Review Master" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="overflowclass">C++ Code Review Master</a>
<p class="overflowclass">组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。</p>
</div>
<a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div> 是轻量值类型,但背后指向的协程帧(frame)在堆上分配;一旦协程结束且 promise_type::final_suspend() 返回 std::suspend_always{},帧不会自动释放——需手动调用 destroy()。若提前 destroy() 了帧,再调用 resume() 就是野指针访问。
- 不要把
std::coroutine_handle存入栈变量并跨作用域使用(比如函数返回局部handle) - 若需长期持有,应确保其生命周期覆盖所有
resume()调用;常见做法是将handle存入任务队列节点或智能指针管理的结构中 -
handle.address() != nullptr && !handle.done()是调用resume()前最简实用检查
resume() 不会自动清理或重入,需自行保证调度安全
resume() 只是跳转回协程上次挂起点继续执行,不重置状态、不重新构造 promise、也不做线程同步。多线程环境下,多个线程并发 resume() 同一个 handle 是未定义行为。
- 务必配对使用:每个挂起点(如
await_suspend)对应一次且仅一次resume(),重复调用导致栈错乱 - 若协程在
await_suspend中把h入队,调度器必须保证只 pop 并resume()一次 - 避免在
await_resume()内部又触发另一次co_await,再由外部恢复——容易形成恢复链断裂或悬空 handle
常见 crash 场景:返回空 handle 或误用 noop_coroutine
最隐蔽的坑是 await_suspend 返回 std::noop_coroutine() 后,又在外层手动 resume()。这时协程早已交由 noop 协程接管,原 handle 已失效,resume() 会跳转到无效地址。
- 错误写法:
std::coroutine_handle await_suspend(std::coroutine_handle h) noexcept { scheduler::enqueue(h); return std::noop_coroutine(); // 协程控制权已移交,h 不再可用 } // 此时再调用 h.resume() → 崩溃 - 正确做法:若需外部恢复,
await_suspend应返回void或bool,并在队列中安全持有h,由调度器显式调用h.resume() - 调试时可加断言:
assert(h.address() != nullptr && h != std::coroutine_handle::from_address(nullptr));
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










