【问题标题】:boost deadline_timer holds reference to objectboost deadtime_timer 持有对对象的引用
【发布时间】:2014-11-21 16:27:21
【问题描述】:

我正在使用 boostdeadline_timer,似乎在删除拥有对象后调用其处理程序。我已经尝试了几种方法来让它发挥作用。

首先我只是通过使用“shared_from_this”绑定到处理程序和拥有对象来使用计时器

m_timer.expires_from_now(boost::posix_time::seconds(m_nHandshakeTimeout));
m_timer.async_wait(
    boost::bind(&CTcpSslSocket::handle_handshake_timeout, 
    shared_from_this(),
    boost::asio::placeholders::error)
    );

此方法使计时器正确运行,但也导致持有对拥有对象的引用。我表明我在关闭应用程序时泄露了拥有对象。不久前我遇到了一个类似的问题,该问题已使用弱指针解决(感谢 stackoverflow 上其他人的帮助)。我通过这样做尝试了与计时器相同的事情:

m_timer.expires_from_now(boost::posix_time::seconds(m_nHandshakeTimeout));
boost::weak_ptr<CTcpSslSocket> weak( shared_from_this() );
m_timer.async_wait([=]( const boost::system::error_code& error ) {
    boost::shared_ptr<CTcpSslSocket> strong(weak);
    if ( strong ) {
        strong->handle_handshake_timeout(error);
    }
    return;
});

就计时器功能而言,这似乎也可以正常工作,但在关闭应用程序时会导致内存损坏。在调试器中运行显示在 boost 代码调用处理程序时发生了异常。

如果我使用定时器的操作在给定时间内完成,我会取消定时器,否则我不会对定时器做任何事情。这是取消代码:

if ( m_eHandshakeTimer != eExpired )
{
    m_eHandshakeTimer = eCanceled;
    m_timer.cancel();
}

关于如何解决这个问题的任何想法?

【问题讨论】:

    标签: c++ boost timer


    【解决方案1】:

    当然,持有一个弱指针并不能保持对象(CTcpSslSocket)的存活。

    弱指针只能观察共享指针拥有的对象的生命周期结束。

    改为共享所有权。这样,当您检测到计时器已取消时,您将自动释放共享对象。

    m_timer.expires_from_now(boost::posix_time::seconds(m_nHandshakeTimeout));
    auto This = shared_from_this();
    m_timer.async_wait([=]( const boost::system::error_code& error ) {
        if (ec != boost::asio::error::operation_aborted) {
            This->handle_handshake_timeout(error); 
               //  ^ could share This with other handlers to keep it alive
        }
        return;
    });
    

    【讨论】:

    • 谢谢 - 但你能解释一下......你的例子(除了使用 lambda)和我原来的 m_timer.async_wait( boost::bind(&CTcpSslSocket::handle_handshake_timeout, shared_from_this( ), boost::asio::placeholders::error) );
    • 我将此标记为答案。乍一看,我认为它与我尝试的第一种方法基本相同,使用“shared_from_this()”。但由于两个原因,这略有不同。首先,“shared_from_this()”实例保存在 lambda 捕获的局部变量中,而在我的尝试中,它被传递给了计时器对象。其次,只有在定时器实际超时时才会调用超时处理程序,而不是在其他事件导致处理程序触发时。
    • 你早了几秒钟 :) 等等:
    • @Ken 没错。要完全清楚“此方法使计时器正确运行,但也会导致对拥有对象的引用”根本不正确 - 充其量是观察错误:MyServiceThing is perfectly freed, as the debug printing shows
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    • 1970-01-01
    • 2016-12-12
    • 2019-08-24
    • 1970-01-01
    • 2012-03-18
    相关资源
    最近更新 更多