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

Boost Asio C++20协程:co_spawn按引用传参出现异常结果

问题:协程参数按引用传递时输出异常的原因分析

现象复现

当session协程的参数使用const std::string&按引用传递时:

#include <boost/asio.hpp>
#include <iostream>

boost::asio::awaitable<void> session(const std::string& name)
{
    std::cout << "Starting " << name << std::endl;
    auto executor = co_await boost::asio::this_coro::executor;
}

int main()
{
    boost::asio::io_context io_context;

    co_spawn(io_context, session("ServerA"), boost::asio::detached);
    co_spawn(io_context, session("ServerB"), boost::asio::detached);

    io_context.run();

    return 0;
}

编译运行后出现异常输出:

> g++ -std=c++20 ../test-coro.cpp -o test-coro && ./test-coro
Starting ServerB
Starting ServerB

而将参数改为按值传递后:

#include <boost/asio.hpp>
#include <iostream>

boost::asio::awaitable<void> session(std::string name)
{
    std::cout << "Starting " << name << std::endl;
    auto executor = co_await boost::asio::this_coro::executor;
}

int main()
{
    boost::asio::io_context io_context;

    co_spawn(io_context, session("ServerA"), boost::asio::detached);
    co_spawn(io_context, session("ServerB"), boost::asio::detached);

    io_context.run();

    return 0;
}

运行结果正常:

> g++ -std=c++20 ../test-coro.cpp -o test-coro && ./test-coro
Starting ServerA
Starting ServerB

请问此现象是预期行为还是编译器/库的Bug?若为预期行为,原因是什么?

环境:Arch Linux 5.18.16-arch1-1,gcc (GCC) 12.2.0,boost版本1.79


回答

这是预期行为,本质是临时对象生命周期与协程调度时机不匹配导致的未定义行为,具体原因如下:

  • 调用session("ServerA")时,会创建一个临时的std::string对象,这个临时对象的生命周期仅局限于当前表达式语句,语句执行完毕后就会被销毁。
  • Boost.Asio的co_spawn函数并不会立刻执行协程体,它会将协程包装成任务加入到io_context的队列中,等待后续调度执行。
  • 当协程真正被调度执行时,原先的临时std::string已经被销毁,此时引用指向的是已释放的内存空间,这属于C++标准中的未定义行为。你看到两次输出"ServerB"只是未定义行为的一种表现形式——比如第一个临时对象的内存被第二个临时对象覆盖,导致两个协程都读取到了后续的值。
  • 改为按值传递时,std::string参数会被拷贝到协程的内部状态中,其生命周期与协程绑定,直到协程执行完毕才会销毁,因此能正确访问参数值。

内容的提问来源于stack exchange,提问作者R.J

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 19:06:32