Reputation: 93
I have an instance of a class A which should register a member callback in another instance of class B. I'm trying to keep the reference to the function of class A inside class B but I get a Segfault.
classA.h:
std::shared_ptr<classB> mB;
void toBeRegisteredCallback(const uint8_t val);
classA.cpp:
classA::classA(std::shared_ptr<classB> b) :
mB(std::move(b)) {
b->registerCallback(std::bind(&classB::toBeRegisteredCallback, this,
std::placeholders::_1));
}
void classB::toBeRegisteredCallback(const uint8_t val) {
LOG(INFO) << "Received a value callback!";
}
Here is the code for classB.h:
public:
void registerCallback(std::function<void(const uint8_t val)> callback);
private:
std::function<void(const uint8_t)> _callback;
Here is code for classB.cpp:
void classB::registerCallback(std::function<void(const uint8_t val)> callback) {
_callback = callback;
}
When I try to call the callback directly without assignment, it works fine:
callback(8)
However, if I try to assign it, I get a segfault at functionswap
Thanks.
Upvotes: 0
Views: 81
Reputation: 12879
Consider your classA
constructor...
classA::classA(std::shared_ptr<classB> b)
: mB(std::move(b))
{
b->registerCallback(std::bind(&classB::toBeRegisteredCallback, this,
std::placeholders::_1));
}
The initialization of mB
will invoke (from here(item 10))...
shared_ptr( shared_ptr&& r ) noexcept;
Move-constructs a shared_ptr from r. After the construction, *this contains a copy of the previous state of r, r is empty and its stored pointer is null.
Hence, in the following statement...
b->registerCallback(std::bind(&classB::toBeRegisteredCallback, this, std::placeholders::_1));
b
is effectively a null pointer resulting in undefined behaviour.
Upvotes: 1
Reputation: 1
I am not quite sure what you want to do, but I created a working example below. You may give me feedback if that helps you, or if you need more explanation. (As already mentioned by john you should be careful with the std::move command)
#include <memory>
#include <functional>
#include <iostream>
class classB
{
public:
classB() {}
~classB() {}
public:
void registerCallback(std::function<void(const uint8_t val)> callback)
{
_callback = callback;
}
void callCallback()
{
if(_callback)
_callback(8);
}
private:
std::function<void(const uint8_t)> _callback;
};
class classA
{
public:
classA(std::shared_ptr<classB> b)
: mB(b)
{
b->registerCallback(std::bind(&classA::toBeRegisteredCallback, this, std::placeholders::_1));
}
~classA(){}
void toBeRegisteredCallback(const uint8_t /*val*/)
{
std::cout << "Received a value callback!" << std::endl;
}
private:
std::shared_ptr<classB> mB;
};
int main(int, char *[])
{
std::shared_ptr<classB> b = std::make_shared<classB>();
classA localClassA = classA(b);
b->callCallback();
system("pause");
}
Upvotes: 0