c ++ bad_weak_ptr错误

时间:2011-04-05 21:25:49

标签: c++ boost

我想创建一些Timer类,每隔N秒打印一次“text”,其中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 个答案:

答案 0 :(得分:27)

问题很可能是在对象实际由共享指针管理之前不能使用shared_from_this。通常,在构造函数中启动线程或异步服务并不是一个好主意,因为您可能不幸并且新线程可能在构造函数完成之前启动,因此在未完全构造的对象上执行。

在您的特定情况下,更糟糕的是,当您在Timer类的构造函数中输入事件循环时,这意味着控件永远不会返回到main,对象永远不会被管理在主要的shared_ptr ...

您应该将通话移至start并将run()的通话移至其他功能,并在实际管理对象后从main 调用该通话在shared_ptr

答案 1 :(得分:10)

在致电shared_from_this()之前,您的课程需要存储在shared_ptr中。这意味着你不能在构造函数中调用shared_from_this(),因为直到构造函数完成之后,对象才会被放入shared_ptr中。

这就是使用enable_shared_from_this的类通常具有start函数的原因,该函数执行需要使用shared_from_this()的初始化的最后步骤。在完全构造对象之后需要调用该start函数,因此不能像你一样从构造函数内部调用它。