mercredi 22 avril 2020

How to safely use callbacks when the binded function could be deleted

In the following code, we are creating an object, bind one function and call it before then after deleting the object.

This obviously leads to a segmentation fault as the underlying object was used after deletion.

In the context of a library providing callbacks for asynchronous data, how are we supposed to prevent callback functions to point to a nullptr?

#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;
}

Returns:

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

Aucun commentaire:

Enregistrer un commentaire