gpt4 book ai didi

c++ - boost::asio::strand 包装导致 shared_from_this 中的 shared_ptr 变为 NULL

转载 作者:搜寻专家 更新时间:2023-10-31 01:34:34 27 4
gpt4 key购买 nike

当我尝试使用 boost::asio::strand wrap 函数时,它似乎导致了来自 shared_ptr >shared_from_this变为NULL,所以第二次执行时,会导致程序崩溃。

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

设置观察点并检查调用堆栈后,此行为似乎是由 shared_ptr 交换值的移动构造函数引起的,它源自 async_result_initBOOST_ASIO_MOVE_CAST

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

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

class object : public boost::enable_shared_from_this<object> {
public:
object()
: service(new boost::asio::io_service),
work(new boost::asio::io_service::work(*service)),
strand(*service),
value(0) {}

void workerThread() {
service->run();
}

void run() {
func_int = strand.wrap(boost::bind(&object::handler_int, shared_from_this(), _1));
func_void = strand.wrap(boost::bind(&object::handler_void, shared_from_this()));

std::thread thread(boost::bind(&object::workerThread, this));

func_int(1);
func_int(1);

func_void();
func_void(); // Will crash due to shared_ptr being NULL, hence "value" cannot be accessed in handler_void

thread.join();
}

void handler_int(int parameter) {
cout << "handler_int: " << value << endl;
}

void handler_void() {
cout << "handler_void: " << value << endl;
}

boost::shared_ptr<boost::asio::io_service> service;
boost::shared_ptr<boost::asio::io_service::work> work;
boost::asio::strand strand;
std::function<void(int)> func_int;
std::function<void(void)> func_void;
int value;
};


int main(int argc, char *argv[]) {
boost::shared_ptr<object> obj(new object());
obj->run();
return 0;
}

最佳答案

这是由于误解了wrap 的作用。这让我最近很困惑。我写信给 asio 的作者进行澄清。他告诉我的话让我很吃惊。

wrap 返回一个“wrapped_handler”,但与您的预期相反,这不是一个在幕后执行分派(dispatch)的函数对象

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

令人困惑的是,这个wrapped_handler 也有一个operator()。这只是执行绑定(bind)函数。它发布或分派(dispatch)函数。在我看来,这个 operator() 不应该存在。我已经寄信给克里斯托弗科尔霍夫表达了这个观点。我还没有收到回复。

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

func_int(1);

用这个:

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

对于绑定(bind)成员函数的每次调用。然后,您可以测试它们是否正在执行 in the strand

请注意,将它们发布/发送到哪个 io_service 并不重要。它们将被直接发送到它们已通过 wrap 关联的链。

最后,关于 asio 和样式。

您可能希望通过 shared_ptr 解决 io_service/strand/work 对象的所有权问题。这总是不必要的。 io_service 是应用程序的基本组件 - 中央消息循环。它不会有不确定的生命周期。工作或链也不会。如果您以以下方式结束其生命周期:

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

一切都会好的。

关于c++ - boost::asio::strand 包装导致 shared_from_this 中的 shared_ptr 变为 NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39220179/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com