Подтвердить что ты не робот

Ошибка С++ bad_weak_ptr

Я хочу создать класс Timer, который печатает "текст" каждые N секунд, где N будет инициализирован в конструкторе.

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>

#include <iostream>

class Timer : public boost::enable_shared_from_this<Timer>
{
public:
    Timer ( const double interval ) : interval_sec( interval )
    {
        io_service_ = new boost::asio::io_service;
        timer_      = new boost::asio::deadline_timer ( * io_service_ );
        start( );
        io_service_ -> run( );
    }

    void start ( )
    {
        timer_ -> expires_from_now( boost::posix_time::seconds( 0 ) );
        timer_ -> async_wait(boost::bind( &Timer::handler
                                        , shared_from_this( )
                                        , boost::asio::placeholders::error
                                        )
                            );
    }

private:
    void handler( const boost::system::error_code& error )
    {
        if ( error )
        {
            std::cerr << error.message( ) << std::endl;
            return;
        }

        printf( "text\n" );
        timer_ -> expires_from_now( boost::posix_time::seconds( interval_sec ) );
        timer_ -> async_wait( boost::bind( &Timer::handler
                                         , shared_from_this( )
                                         , boost::asio::placeholders::error
                                         )
                            );
    }

private:
    boost::asio::io_service * io_service_;
    boost::asio::deadline_timer * timer_;
    double interval_sec;
};

int main()
{
    boost::shared_ptr<Timer> timer( new Timer ( 10 ) );
    return 0;
}

Но у меня ошибка bad_weak_ptr.

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_weak_ptr> >'
  what():  tr1::bad_weak_ptr
Aborted

Что я делаю неправильно и как его исправить?

4b9b3361

Ответ 1

Вероятно, проблема заключается в том, что вы не можете использовать shared_from_this, пока объект не будет управляться общим указателем. В общем случае не рекомендуется запускать нить или асинхронную службу в конструкторе, так как вам может быть не повезло, и новый поток может начаться до завершения конструктора и, таким образом, выполнять не полностью сконструированный объект.

В вашем конкретном случае это еще хуже, поскольку вы вводите цикл событий внутри конструктора вашего класса Timer, а это означает, что элемент управления никогда не возвращается в main, объект никогда не управляется shared_ptr в основном...

Вы должны перевести вызов на start и вызов run() на другую функцию и вызвать это из main после фактического управления объектом в shared_ptr.

Ответ 2

Перед вызовом shared_from_this() ваш класс должен быть сохранен в shared_ptr. Это означает, что вы не можете вызвать shared_from_this() внутри конструктора, потому что строка не будет помещена в объект shared_ptr до завершения конструктора.

Именно поэтому классы, которые используют enable_shared_from_this, обычно имеют функцию start, которая выполняет заключительные шаги инициализации, требующие использования shared_from_this(). Эта функция запуска должна вызываться после того, как объект полностью сконструирован и поэтому не может быть вызван изнутри конструктора, как вы это делаете.