Vog*_*ang 5 c++ clang address-sanitizer c++20 c++-coroutine
handle.destroy()从 C++ 协程的最终暂停中调用是否有效?
根据我的理解,这应该没问题,因为协程当前已暂停并且不会再次恢复。
尽管如此,AddressSanitizer 仍会报告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\n";
co_return;
}
int main() {
auto x = foo();
}
Run Code Online (Sandbox Code Playgroud)
当使用 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中找到完整的代码)
这是我的代码中的问题还是 AddressSanitizer 中的错误肯定?
如果您 100% 确定之后没有人会使用协程 Promise,那么它是完全有效的。调用coroutine_handle::destroy相当于调用协程 Promise 析构函数。
既然如此,那当初为什么要这样做呢?刚刚std::suspend_never从final_suspend
std::suspend_never final_suspend() const noexcept { return {}; }
Run Code Online (Sandbox Code Playgroud)
它相当于你的代码。final_suspend如果我们想在协程完成后用协程 Promise 做一些有意义的事情,比如返回协程存储的结果,那么我们想要挂起协程。由于您的task对象不存储或返回任何内容,我不明白为什么要最终挂起它。
请注意,如果您使用第三方库,例如我的concurrencpp,您需要确保可以销毁不属于您的承诺。协程 Promise 可能会被挂起,但仍被其他地方引用coroutine_handle。这又回到了第一点。就我的库而言,它是不安全的,因为对象可能result仍然引用它。
总之,在以下情况下可以调用coroutine_promise::destroy:
final_suspend它时)destroy之前没有被调用过(双删除)| 归档时间: |
|
| 查看次数: |
1077 次 |
| 最近记录: |