2017-11-21 6 views
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(); 
} 

答えて

0

私はラムダキャプチャawait_suspend機能で&を見落としています。したがって、coroutine_handleはこの呼び出しの後に破棄されます。

関連する問題