Reputation: 945
I'm debugging some code and I ran across this snippet that was crashing, the problem is that the singleton pointer and the local pointer are not the same address. I'm not sure why that is.
The code roughly looks like this:
class B;
class I_A : public std::enable_shared_from_this<I_A> {
public:
virtual std::shared_ptr<B> make() = 0;
};
class A : public I_A {
public:
std::shared_ptr<B> make() override {
return std::make_shared<B>(shared_from_this());
}
};
static std::shared_ptr<I_A> getInstance() {
static std::shared_ptr<I_A> ptr;
if(!ptr) {
std::cout << "Making new instance\n";
ptr = std::make_shared<A>();
}
std::cout << "Ptr is " << ptr << '\n';
return ptr;
}
class B {
public:
B(const std::shared_ptr<I_A>& ptr) : ptr(ptr) {
std::cout << "In B() " << ptr << '\n';
}
void foo() {
std::cout << "B::ptr " << ptr << '\n';
assert(ptr == getInstance());
}
private:
const std::shared_ptr<I_A>& ptr; // Potential problem here
};
int main() {
auto bPtr = getInstance()->make();
bPtr->foo();
}
But if I store a copy of shared_ptr<I_A>
in B instead of storing a ref, everything works fine.
If my understanding is correct, the singleton should never change the address, but the B::ptr
and getInstance()
have different addresses.
Any idea why that is?
Upvotes: 4
Views: 554
Reputation: 63117
You should (approximately) never use const std::shared_ptr<T>&
, for any T
. Just use a std::shared_ptr<T>
. Would you use a T * const &
?
The problem you are observing is that the instance of std::shared_ptr<I_A>
that you get from A::shared_from_this()
is a temporary, and it has ceased to exist by the time you can use your B
. You then use a dangling reference, which has undefined behaviour.
Upvotes: 6