c++ - gcc 10 在 co_await 表达式完成之前销毁传递给返回等待器类型的函数的临时参数
问题描述
我在 windows 10 上的 wsl 1 上使用 gcc 10 和协程,并注意到传递给返回等待程序的函数的参数在协程挂起时被销毁
clang 和 msvc 不这样做,而是保留临时变量,直到表达式完成
演示问题的代码:
#include <cstdio>
#include <thread>
#if defined __clang__ || defined _WIN32
#include <experimental/coroutine>
using coro_handle = std::experimental::coroutine_handle<>;
using suspend_never = std::experimental::suspend_never;
#else
#include <coroutine>
using coro_handle = std::coroutine_handle<>;
using suspend_never = std::suspend_never;
#endif // __clang__
struct arg_t
{
arg_t() { printf("arg_t()\n"); }
~arg_t()
{
printf("~arg_t()\n");
}
};
struct awaiter_t
{
awaiter_t() { printf("awaiter_t()\n"); }
~awaiter_t()
{
printf("~awaiter_t()\n");
}
bool await_ready() const noexcept
{
printf("await_ready()\n");
return false;
}
void await_suspend(coro_handle coro)
{
printf("await_suspend()\n");
std::thread([coro]() mutable { std::this_thread::sleep_for(std::chrono::seconds(3)); coro.resume(); }).detach();
}
void await_resume()
{
printf("await_resume()\n");
}
};
struct task_t
{
struct promise_type
{
task_t get_return_object() { return {}; }
suspend_never initial_suspend() noexcept { return {}; }
suspend_never final_suspend() noexcept { return {}; }
void unhandled_exception() noexcept { std::terminate(); }
void return_void() {}
};
task_t() = default;
};
awaiter_t make_awaiter(const arg_t& arg)
{
return awaiter_t{};
}
task_t test_awaiter()
{
co_await make_awaiter(arg_t{});
}
int main()
{
test_awaiter();
std::this_thread::sleep_for(std::chrono::seconds(4));
return 0;
}
gcc 测试:https ://godbolt.org/z/cT4q8d
使用 gcc 标志编译:-std=c++20 -Wall -pthread -fcoroutines
输出:
arg_t()
awaiter_t()
~arg_t() -> destroyed before await_ready !
await_ready()
await_suspend()
await_resume()
~awaiter_t()
铿锵测试:https ://godbolt.org/z/fcrzPM
用clang标志编译:-std=c++20 -Wall -pthread -stdlib=libc++
输出:
arg_t()
awaiter_t()
await_ready()
await_suspend()
await_resume()
~awaiter_t()
~arg_t() -> destroyed after the awaiter is destroyed
msvc 的行为也像我在这里尝试的 clang:Do temporaries 传递给返回 awaitable 的函数在使用 co_await 的挂起点后仍然有效
它是 gcc 中的错误吗?还是编译器可以在这里随意做任何事情?
解决方案
推荐阅读
- python - 如何在 Python 代码的 HTML 部分中显示 Python 字典键和值对
- discord - Discord.js - 如何禁止不在服务器中的人?|| “错误 [BAN_RESOLVE_ID]:无法解析要禁止的用户 ID。”
- scala - 这个scala错误对类型不匹配意味着什么?
- r - 将函数应用于所有列组合对并提取 pvalues
- python-3.x - 将字段添加到 Elasticsearch 索引
- ant-media-server - 在 Ant Media Server 中添加只支持 UDP 不支持 TCP 的 Stream Source
- wear-os - 如何使用 WearableDrawerLayout 支持多屏 Wear OS 应用
- powerbi-desktop - 具有较早功能的 power bi rankx
- java - 使用 HttpURLConnection 将带有参数的 POST 请求从 java 发送到 php 文件
- python - 有没有一种简单的方法可以在熊猫数据框中找到元素的“坐标”?