C++ gcc 10在co_wait表达式完成之前销毁传递给返回等待器类型的函数的临时参数
我在windows 10上使用gcc 10和wsl 1上的协程,注意到传递给返回等待程序的函数的参数在协程挂起时被销毁 clang和msvc不这样做,但保留临时值,直到表达式完成 演示问题的代码:C++ gcc 10在co_wait表达式完成之前销毁传递给返回等待器类型的函数的临时参数,c++,g++,clang++,c++20,c++-coroutine,C++,G++,Clang++,C++20,C++ Coroutine,我在windows 10上使用gcc 10和wsl 1上的协程,注意到传递给返回等待程序的函数的参数在协程挂起时被销毁 clang和msvc不这样做,但保留临时值,直到表达式完成 演示问题的代码: #include <cstdio> #include <thread> #if defined __clang__ || defined _WIN32 #include <experimental/coroutine> using coro_handle = std
#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;
}
叮当声测试:
使用铿锵标志编译:-std=c++20-Wall-pthread-stdlib=libc++
输出:
arg_t()
awaiter_t()
~arg_t() -> destroyed before await_ready !
await_ready()
await_suspend()
await_resume()
~awaiter_t()
arg_t()
awaiter_t()
await_ready()
await_suspend()
await_resume()
~awaiter_t()
~arg_t() -> destroyed after the awaiter is destroyed
msvc的行为也像我在这里试验的叮当声:
它是gcc中的一个bug吗?或者编译器在这里可以自由执行任何它喜欢的操作?是的,这是gcc中的一个错误,但我正在使用10.1.0版,这个错误还没有修复。这里也提到过,它似乎是固定在gcc主干中的。作为解决方法,您可以使用局部变量。。。但这是一个编译器错误。是的,这是gcc中的一个错误,但我正在使用10.1.0版,这个错误还没有修复。这里也提到过,它似乎是固定在gcc主干中的。作为解决方法,您可以使用局部变量。。。但这是一个编译器错误。