【问题标题】:How does shared_from_this in std::bind work where object does not exist?std::bind 中的 shared_from_this 在对象不存在的情况下如何工作?
【发布时间】:2016-05-29 21:01:05
【问题描述】:

该代码安全吗?

class C : public std::enable_shared_from_this<C> {
    void start() {
             boost::asio::async_write(socket_, boost::asio::buffer(message_), 
             std::bind(&tcp_connection::handle_write, shared_from_this(),
             _1, _2));
    };
    // ...
};

class D {
    void start()
    {
         std::shared_ptr<C> cptr = std::make_shared<C>(); // (1)
         cptr->start();
    } // (2)
};

如果消息很长,async_write 操作可能需要很长时间。

在点 (1) 只有一个 shared_ptr 指向 C 对象。 start() 被调用,start() 完成并且在 (2) 变量 cptr 超出范围并被销毁。

async_write完成写操作后,回调被调用;这会导致崩溃,因为shared_from_this() 尝试将shared_ptr 设置为不存在的对象。

对将要发生的事情的描述是否正确?

【问题讨论】:

    标签: c++ c++11 boost-asio bind shared-ptr


    【解决方案1】:

    不,你错了。

    shared_from_this() 的调用发生在start 返回之前。生成的shared_ptr 的副本由bind 的结果保存。

    因此,当您到达 (2) 时,对该对象的两个引用中只有一个已经消失,并且它仍然存在

    【讨论】:

    • 非常感谢。我不想写新问题。我还想知道如果在上面的代码中处理程序不是一个方法(所以在绑定中没有shared_from_thisthis) - 处理程序将是一个函数。在 D::start 中,我创建了普通变量:C c。如果 c 在 async_write 完成之前被销毁可以吗?在这种情况下调用回调总是可以的吗?
    • 视情况而定。如果处理程序以任何方式(例如通过某些指针或引用)访问c,那么您就有问题了。如果没有,那很好。 (另一种选择是将c 的副本传递给处理程序;这是否有效取决于处理程序的详细信息。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 2012-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多