未使用co_return的boost::asio::awaitable协程结束是否为未定义行为?
我想请教:未使用co_return就直接结束boost::asio::awaitable类型的协程是否属于未定义行为(UB)?我在Boost官方文档里没有找到相关的明确说明。
根据Cppreference的内容:如果协程的Promise类型没有定义return_void(),那么协程自然结束(不写co_return)属于未定义行为;反之,无论使用co_return还是让协程自然结束,都会调用promise.return_void()。
但我在实际测试中发现了异常行为,似乎指向未定义行为:
测试代码如下:
#include <iostream> #include <thread> #include <boost/asio.hpp> boost::asio::awaitable<void> coroutineA() { std::cout << "coroutineA" << std::endl; } boost::asio::awaitable<void> coroutineB() { std::cout << "coroutineB" << std::endl; co_return; } int main() { boost::asio::io_context context; auto waitA= boost::asio::co_spawn(context, coroutineA(), boost::asio::use_future); // 似乎触发了UB auto waitB = boost::asio::co_spawn(context, coroutineB(), boost::asio::use_future); std::thread t([&context] () { context.run(); }); waitA.get(); waitB.get(); t.join(); }
运行coroutineA会导致程序崩溃,在其他测试案例中还出现过程序返回非零值但无阻塞执行的情况。
我查看Boost 1.82的源码时发现:asio/impl/awaitable.hpp中,template <typename Executor> class awaitable_frame<void, Executor>和template <typename Executor> class awaitable_frame<awaitable_thread_entry_point, Executor>都定义了void return_void()。按照我的理解,前者就是这两个协程所使用的Promise类型。
根据Cppreference的说明,不管是co_return还是协程自然结束,都会调用promise.return_void(),而这里的awaitable_frame::return_void()是已定义的,理论上不应该出现问题。
所以我再次确认:未使用co_return就结束boost::asio::awaitable协程是否属于未定义行为?如果是,原因是什么?能否给出文档参考,或者指出我的推理漏洞?
内容的提问来源于stack exchange,提问作者Superlokkus

