C++ coroutines: Is it valid to call `handle.destroy` from the final suspend point?(C++协程:从最后一个挂起点调用`handle.delety`是否有效?)
问题描述
从C++协程的最终挂起中调用handle.destroy()
是否有效?
根据我的理解,这应该很好,因为协程当前已暂停,不会再次恢复。
仍然,AddressSaniizer报告以下代码片段的heap-use-after-free
:
#include <experimental/coroutine>
#include <iostream>
using namespace std;
struct final_awaitable {
bool await_ready() noexcept { return false; }
void await_resume() noexcept {}
template<typename PROMISE> std::experimental::coroutine_handle<> await_suspend(std::experimental::coroutine_handle<PROMISE> coro) noexcept {
coro.destroy(); // Is this valid?
return std::experimental::noop_coroutine();
}
};
struct task {
struct promise_type;
using coro_handle = std::experimental::coroutine_handle<promise_type>;
struct promise_type {
task get_return_object() { return {}; }
auto initial_suspend() { return std::experimental::suspend_never(); }
auto final_suspend() noexcept { return final_awaitable(); }
void unhandled_exception() { std::terminate(); }
void return_void() {}
};
};
task foo() {
cerr << "foo
";
co_return;
}
int main() {
auto x = foo();
}
当使用clang 11.0.1和编译标志-stdlib=libc++ --std=c++17 -fcoroutines-ts -fno-exceptions -fsanitize=address
编译时。(参见https://godbolt.org/z/eq6eoc)
(我实际代码的简化版本。您可以在https://godbolt.org/z/8Yadv1)
中找到完整的代码这是我的代码中的问题还是AddressSaniizer中的错误肯定?
推荐答案
如果您100%确定以后没有人会使用协程承诺,则它完全有效。调用coroutine_handle::destroy
等同于调用协程承诺析构函数。
final_suspend
返回std::suspend_never
std::suspend_never final_suspend() const noexcept { return {}; }
它等同于您的代码。如果我们想在协程结束后对协程承诺做一些有意义的事情,比如返回协程的存储结果,那么我们希望在final_suspend
中暂停协程。由于您的task
对象不存储或返回任何内容,我看不出为什么要最终挂起它。
coroutine_handle
在其他地方引用。回到第1点。对于我的库,它不安全,因为可能是result
对象仍在引用它。
总之,可以调用coroutine_promise::destroy
if:
- 协程暂停(当您达到
final_suspend
时) - 销毁后没有人会使用该协程承诺(请特别确保不存在引用该协程、类似于未来的对象!)
destroy
之前未调用(双删除)
这篇关于C++协程:从最后一个挂起点调用`handle.delety`是否有效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:C++协程:从最后一个挂起点调用`handle.delety`是否有效?


基础教程推荐
- C++,'if' 表达式中的变量声明 2021-01-01
- C++ 标准:取消引用 NULL 指针以获取引用? 2021-01-01
- 什么是T&&(双与号)在 C++11 中是什么意思? 2022-11-04
- C++ 程序在执行 std::string 分配时总是崩溃 2022-01-01
- 调用std::Package_TASK::Get_Future()时可能出现争用情况 2022-12-17
- 运算符重载的基本规则和习语是什么? 2022-10-31
- 如何在 C++ 中处理或避免堆栈溢出 2022-01-01
- 您如何将 CreateThread 用于属于类成员的函数? 2021-01-01
- 如何定义双括号/双迭代器运算符,类似于向量的向量? 2022-01-01
- 设计字符串本地化的最佳方法 2022-01-01