C++20协程co_return后main函数未执行完毕看似挂起问题求解
问题原因
核心问题是void_future的协程承诺类型final_suspend返回值设计错误导致的未定义行为:
void_future::promise_type::final_suspend当前返回std::suspend_never,当call_coroutine协程执行完co_return逻辑后,会进入final_suspend流程,此时返回suspend_never意味着协程框架会立刻自动销毁整个协程状态(包含promise对象本身),不需要等待手动调用destroy。- 协程是在
main函数中通过ret.resume()触发执行的,协程在resume调用的执行栈内销毁了自身状态,会直接导致resume()调用无法正常返回,后续main函数里的打印逻辑永远不会被执行。同时void_future析构时还会对已经销毁的协程句柄二次调用destroy,进一步触发未定义行为,程序直接崩溃退出。
从运行输出可以佐证:日志中没有出现promise_type destructor void和void_future destructor的记录,说明resume没有返回,main没有执行完毕,栈上的ret对象没有触发析构,协程状态已经被提前自动销毁。
解决方案
只需要修改void_future::promise_type::final_suspend的返回值为std::suspend_always即可:
auto final_suspend() noexcept(true) { std::cout<<"final_suspend void"<<std::endl; return std::suspend_always(); // 替换原有suspend_never返回值 }
修改后逻辑符合协程生命周期的设计预期:
call_coroutine执行完co_return后,进入final_suspend挂起点,不会自动销毁协程状态,resume()可以正常返回,main函数后续的打印会正常执行。main函数执行结束时,栈上的ret对象触发析构,调用co_handle_.destroy()手动销毁协程状态,所有析构日志都会正常打印,不存在未定义行为。
内容的提问来源于stack exchange,提问作者Johnny Martin
相关产品推荐
相关产品推荐

