ошибка c ++ bad_weak_ptr - PullRequest
13 голосов
/ 06 апреля 2011

Я хочу создать некоторый класс 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

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

Ответы [ 2 ]

27 голосов
/ 06 апреля 2011

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

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

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

11 голосов
/ 06 апреля 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...