boost :: asio :: strand wrap导致shared_from_this中的shared_ptr变为NULL

时间:2016-08-30 06:24:37

标签: c++ boost-asio

当我尝试使用boost::asio::strand wrap函数时,似乎会导致来自shared_ptr的{​​{1}}变为NULL,因此当它第二次执行时,它会导致程序崩溃。

但是,只有绑定的函数采用无参数时才会发生这种情况。

设置监视点并检查callstack后,此行为似乎是由shared_from_this交换值的移动构造函数引起的,该构造函数源自shared_ptr async_result_init

我的问题是,我应该如何正确使用BOOST_ASIO_MOVE_CAST来避免这种情况发生?

下面是一个简单的示例,向您展示我的意思:

wrap

1 个答案:

答案 0 :(得分:3)

这是由于对wrap所做的事情的误解。这最近引起了我的兴趣。我写信给asio的作者澄清。他告诉我的事让我感到惊讶。

wrap会返回'wrapped_handler',但与您的预期相反,这不是一个在封面下执行调度的函数对象

它实际上是一个包含您绑定的处理程序的对象以及对执行程序的引用。 Asio io对象在完成异步操作时使用此信息,以便在正确的上下文中执行处理程序。

令人困惑的是,此wrapped_handler也有operator()。这样做只是执行绑定功能。它发布或发送功能。在我看来,operator()不应该存在。我已经邮寄了克里斯托弗科尔霍夫表达这种观点。我没有回复。

你可以通过替换它来证明这一点:

func_int(1);

用这个:

service->post(strand->wrap(boost::bind(&object::handler_int, shared_from_this(), 1)));

对于绑定成员函数的每个调用。然后,您可以测试他们是否在中执行

请注意,您发布/发送给他们的io_service无关紧要。它们将被wrap直接发送到与之关联的链。

最后,关于asio和风格。

您可能希望通过shared_ptr解决io_service / strand / work对象的所有权问题。这始终是不必要的。 io_service是应用程序的基本组件 - 中央消息循环。它不会有不确定的生命。工作或链条也不会。只要您终身使用:

service.stop();
thread(s).join();

一切都会好的。