1
次のコードでは、有効なコルーチンサポートを持つclang-5.0でSEGFAULTが発生します。 あなたはここでオンラインのコードを実行することができます。 wandbox compiled codeコルーチンでラップされたboostタイマータイマーがclang-5.0でSEGFAULTを引き起こす
を私はコンパイラオプションを使用しています:
-stdlib=libc++ -fcoroutines-ts
私はGDBの下でそれを実行すると、それはcoro.resume(後async_awaitでセグメンテーションフォールト)。が呼び出されます。 await_resume関数には決して達しません。 これはオブジェクトの生涯の問題であると私は期待しています。非常に同じコードがMSVC 2017で問題なくコンパイルされ、実行されます。
プログラムの出力は次のようになります。
i=0
Segmentation fault
Finish
ソースコード:
#define BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION // Enables future::then
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/asio/system_timer.hpp>
#include <experimental/coroutine>
#include <chrono>
#include <iostream>
namespace std
{
namespace experimental
{
template <typename... Args>
struct coroutine_traits<boost::future<void>, Args...> {
struct promise_type {
boost::promise<void> p;
auto get_return_object() { return p.get_future(); }
std::experimental::suspend_never initial_suspend() { return {}; }
std::experimental::suspend_never final_suspend() { return {}; }
void unhandled_exception(){}
void return_void() { p.set_value(); }
};
};
}
}
namespace asioadapt
{
using namespace std::experimental;
template <typename R> auto operator co_await(boost::future<R> &&f) {
struct Awaiter {
boost::future<R> &&input;
boost::future<R> output;
bool await_ready() { return false; }
auto await_resume() { return output.get(); }
void await_suspend(std::experimental::coroutine_handle<> coro) {
input.then([this, coro](auto result_future) mutable{
this->output = std::move(result_future);
coro.resume();
});
}
};
return Awaiter{ static_cast<boost::future<R>&&>(f) };
}
template <typename R, typename P>
auto async_await(boost::asio::system_timer &t, std::chrono::duration<R, P> d) {
struct Awaiter
{
boost::asio::system_timer &t;
std::chrono::duration<R, P> d;
boost::system::error_code ec;
bool await_ready() { return false; }
void await_suspend(std::experimental::coroutine_handle<> coro) {
t.expires_from_now(d);
t.async_wait([this, &coro](auto ec) mutable {
this->ec = ec;
coro.resume();
});
}
void await_resume() {
if (ec)
throw boost::system::system_error(ec);
}
};
return Awaiter{ t, d };
}
}
using namespace boost;
using namespace boost::asio;
using namespace std::chrono_literals;
using namespace asioadapt;
boost::future<void> sleepy(io_service &io, int &i) {
system_timer timer(io);
std::cout << "i=" << i << std::endl;
co_await async_await(timer, 100ms);
++i;
std::cout << "i=" << i << std::endl;
co_await async_await(timer, 100ms);
++i;
std::cout << "i=" << i << std::endl;
co_await async_await(timer, 100ms);
++i;
std::cout << "i=" << i << std::endl;
}
void test(){
int i = 0;
io_service io;
auto future = sleepy(io, i);
io.run();
std::cout << "i=" << i << std::endl;
}
int main()
{
test();
}