当我尝试使用boost::asio::strand
wrap
函数时,似乎会导致来自shared_ptr
的{{1}}变为NULL,因此当它第二次执行时,它会导致程序崩溃。
但是,只有绑定的函数采用无参数时才会发生这种情况。
设置监视点并检查callstack后,此行为似乎是由shared_from_this
交换值的移动构造函数引起的,该构造函数源自shared_ptr
async_result_init
。
我的问题是,我应该如何正确使用BOOST_ASIO_MOVE_CAST
来避免这种情况发生?
下面是一个简单的示例,向您展示我的意思:
wrap
答案 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();
一切都会好的。