2017-11-21 2 views
1

다음 코드는 활성화 된 동시 루틴을 지원하는 clang-5.0에서 SEGFAULT를 발생시킵니다.() 나는 GDB 아래를 실행하면coroutines에 래핑 된 부스트 타이머가 clang-5.0에서 SEGFAULT를 일으 킵니다.

-stdlib=libc++ -fcoroutines-ts 

그것이 coro.resume 후 async_await에서 세그먼테이션 폴트 (segfault); 내가 컴파일러 옵션을 사용하고 wandbox compiled code

: 온라인으로 여기에 코드를 실행할 수 있습니다 호출됩니다. 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은이 호출 후에 파괴됩니다.

관련 문제