C++协程done()函数同一循环返回值异常问题排查
协程
done()返回值异常问题解析 问题现象
这段代码在g++ 12、13、14版本编译运行时,会出现一处异常输出(某条结果为done: 0),但clang 18、19版本运行完全正常(所有输出均为done: 1):
Program returned: 0
done: 1
done: 1
done: 1
done: 1
done: 1
done: 0 <-- 异常结果
done: 1
done: 1
done: 1
done: 1
按照逻辑,由于initial_suspend()返回suspend_never,协程创建后会立即执行到final_suspend阶段,此时调用coroutine_handle::done()应该返回true,但出现了不符合预期的false值,需要明确问题根源。
代码示例
#include <coroutine> #include <iostream> #include <vector> struct Task { struct promise_type { Task get_return_object() { return {.h = std::coroutine_handle<>::from_address(this)}; } std::suspend_never initial_suspend() noexcept { return {}; } std::suspend_always final_suspend() noexcept { return {}; } void unhandled_exception() {} void return_void() {} }; std::coroutine_handle<> h; }; Task coro() { co_return; } int main() { std::vector<Task> v; for (int i = 0; i < 10; ++i) v.push_back(coro()); for (auto &t : v) std::cout << "done: "<< t.h.done() << "\n"; return 0; }
问题根源
这是GCC编译器的协程实现bug,同时代码存在内存泄漏风险,但该风险与done()返回值异常无关。
具体分析
- 标准行为预期:根据C++标准,当协程执行到
final_suspend时,coroutine_handle::done()必须返回true——此时协程已经完成所有用户逻辑,仅处于挂起等待销毁的状态。 - GCC的实现错误:测试发现,当
vector::push_back触发Task的移动操作后,GCC错误地保留了旧的协程状态标记,导致部分协程实例的done()返回false。而Clang正确处理了协程移动后的状态跟踪,符合标准预期。 - 代码的潜在问题:代码中未调用
coroutine_handle::destroy()销毁协程帧,会导致内存泄漏,但这和done()返回值异常没有关联,属于独立问题。
结论
- 核心问题是GCC的协程实现bug,错误报告了已完成协程的状态。
- 代码本身没有违反C++标准的编程错误,也不属于未定义行为范畴。
内容的提问来源于stack exchange,提问作者Ralph Zhang
相关产品推荐
相关产品推荐

