gpt4 book ai didi

c++ - 可以删除绑定(bind)函数时如何安全地使用回调

转载 作者:行者123 更新时间:2023-12-01 14:48:06 25 4
gpt4 key购买 nike

在下面的代码中,我们正在创建一个对象,绑定(bind)一个函数并在删除该对象之前调用它。

这显然会导致段错误,因为底层对象在删除后被使用。

在为异步数据提供回调的库上下文中,我们应该如何防止回调函数指向 nullptr

可以在cpp.sh/5ubbg上测试

#include <memory>
#include <functional>
#include <iostream>

class CallbackContainer {
public:
std::string data_;
CallbackContainer(std::string data): data_(data) {}
~CallbackContainer() {}
void rawTest(const std::string& some_data);
};

void CallbackContainer::rawTest(const std::string& some_data) {
std::cout << data_ << " " << some_data << std::endl;
}

int main(int /* argc */, char const** /* argv */) {
std::unique_ptr<CallbackContainer> container;
container.reset(new CallbackContainer("Internal data"));

auto callback = std::bind(&CallbackContainer::rawTest, container.get(), std::placeholders::_1);
callback("Before");
std::cout << &callback << std::endl;
container.reset();
std::cout << &callback << std::endl;
callback("After");
return 0;
}

返回:

> Internal data Before 
> 0x7178a3bf6570
> 0x7178a3bf6570
> Error launching program (Segmentation fault)

最佳答案

如果您可以共享所有权,请执行以下操作:

int main(int /* argc */, char const** /* argv */) {
std::shared_ptr<CallbackContainer> container; // shared pointer
container.reset(new CallbackContainer("Internal data"));
// shared with functor
auto callback = std::bind(&CallbackContainer::rawTest, container, std::placeholders::_1);
callback("Before");
std::cout << &callback << std::endl;
container.reset();
std::cout << &callback << std::endl;
callback("After");
return 0;
}

如果不是,您应该以某种方式显式地将无效性传递给函数对象。这假设您知道容器何时被删除,并在 之前手动明确地使其失效:

int main(int /* argc */, char const** /* argv */) {
std::unique_ptr<CallbackContainer> container;
container.reset(new CallbackContainer("Internal data"));
std::atomic<CallbackContainer*> container_raw(container.get());
auto callback = [&container_raw] (std::string data)
{
if (auto c = container_raw.load())
c->rawTest(data);
};
callback("Before");
std::cout << &callback << std::endl;
container_raw.store(nullptr);
container.reset();
std::cout << &callback << std::endl;
callback("After");
return 0;
}

对于asio情况,通常使用shared_from_this(),比如std::bind(&MyClass::MyMemFunc, shared_from_this(), ptr);

关于c++ - 可以删除绑定(bind)函数时如何安全地使用回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61360300/

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