协程接收聚合参数时出现Double-free错误:Bug还是未定义行为?
GCC 11-12中协程代码的Double-free问题分析
问题场景
以下C++协程代码在最新版GCC和Clang中运行正常,但在GCC 11至GCC 12版本中会触发Double-free错误,汇编代码中可观察到对std::string的重复析构调用。
复现代码
#include <coroutine> #include <iostream> #include <string> struct Coro{ struct Promise; struct Awaiter{ bool await_ready(){return true;} void await_resume(){} void await_suspend(std::coroutine_handle<Promise> coro){} }; struct Promise{ Coro get_return_object(){return {};} auto initial_suspend() noexcept{return std::suspend_never{};} auto final_suspend() noexcept{return std::suspend_never{};} void unhandled_exception(){} Awaiter await_transform(const Coro&){ return {}; } void return_void(){} }; using promise_type = Promise; }; struct Aggregate{ //(*) //Aggregate(const std::string& s):s{s}{} std::string s; }; static_assert(std::is_aggregate_v<Aggregate>); Coro f1(Aggregate){ co_return; } Coro f2(std::string){ co_return; } Coro g(){ std::string foo{"foo"}; // 1. 触发Double-free的写法 co_await f1(Aggregate{"/"+foo}); // 2. 正常的写法(取消注释调用f2) //co_await f2("/" + foo); // 3. 正常的写法(取消注释拆分调用与co_await) //Coro c = f1(Aggregate{"/"+foo}); //co_await c; } int main(){ g(); }
问题分析
现象验证
在GCC 12.3生成的汇编代码中,可清晰看到对std::string的两次析构调用,即Double-free:
call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() [complete object destructor] jmp .L168 mov rbx, rax .L168: mov rax, QWORD PTR [rbp-40] add rax, 40 mov rdi, rax call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() [complete object destructor] mov rax, rbx
结论:这是GCC编译器Bug
该问题属于GCC 11-12版本的编译器Bug,并非C++标准定义的未定义行为。原因是编译器在处理协程中co_await表达式内的聚合初始化临时对象时,错误地重复插入了析构调用,导致临时std::string被两次释放。
相关Bug报告
该问题对应GCC Bugzilla中的核心Bug条目:
- Bug 105547:协程中传递聚合类型临时参数时触发重复析构
- Bug 106243:优化阶段错误处理协程内临时对象的销毁时机
这些Bug已在GCC 13及后续版本中修复,因此最新版GCC不再出现该问题。
临时解决方案
以下任一修改可消除Double-free错误:
- 在
Aggregate中添加用户定义构造函数(取消注释标记(*)的代码),使其不再是聚合类型 - 直接传递
std::string给函数(取消注释代码中2.部分,调用f2) - 将
f1的调用与co_await拆分到不同行(取消注释代码中3.部分)
注:将f1的参数改为引用传递无法解决该问题。
内容的提问来源于stack exchange,提问作者Weijun Zhou
相关产品推荐
相关产品推荐

