简体   繁体   中英

c++ bad_weak_ptr error

I want to create some Timer class, which prints "text" every N seconds, where N will be initialized in constructor.

#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;
}

But I have bad_weak_ptr error.

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

What am I doing wrong and how can I fix it?

The problem is most probably that you cannot use shared_from_this until the object is actually managed by a shared pointer. In general it is not a good idea to launch a thread or asynchronous service in the constructor, as you might be unlucky and the new thread might start before the constructor has completed and thus execute on a not fully constructed object.

In your particular case it is even worse, as you are entering the event loop inside the constructor of your Timer class, and that means that control never returns to main , the object is never managed by the shared_ptr in main...

You should move the call to start and the call to run() to a different function, and call that from main after the object is actually managed in the shared_ptr .

Before calling shared_from_this() your class needs to be stored in a shared_ptr . This means that you cannot call shared_from_this() inside the constructor, because the line the object won't be placed into the shared_ptr until after the constructor is finished.

This is the reason that classes which use enable_shared_from_this typically have a start function which does the final steps of initialization that require the use of shared_from_this() . That start function needs to be called after the object is completely constructed, and so cannot be called from inside the constructor as you are doing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM