You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()返回值异常无关。

具体分析

  1. 标准行为预期:根据C++标准,当协程执行到final_suspend时,coroutine_handle::done()必须返回true——此时协程已经完成所有用户逻辑,仅处于挂起等待销毁的状态。
  2. GCC的实现错误:测试发现,当vector::push_back触发Task的移动操作后,GCC错误地保留了旧的协程状态标记,导致部分协程实例的done()返回false。而Clang正确处理了协程移动后的状态跟踪,符合标准预期。
  3. 代码的潜在问题:代码中未调用coroutine_handle::destroy()销毁协程帧,会导致内存泄漏,但这和done()返回值异常没有关联,属于独立问题。

结论

  • 核心问题是GCC的协程实现bug,错误报告了已完成协程的状态。
  • 代码本身没有违反C++标准的编程错误,也不属于未定义行为范畴。

内容的提问来源于stack exchange,提问作者Ralph Zhang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 05:21:17