I'm storing a class (let's call it A
) in an std::vector
using C++ smart pointers (so the vector sigature is std::vector<std::shared_ptr<A>>
).
#include <iostream>
#include <memory>
#include <vector>
class A : std::enable_shared_from_this<A> {
public:
void doWork();
std::shared_ptr<A> getSharedRef();
};
void A::doWork() { std::cout << "Working..." << std::endl; }
std::shared_ptr<A> A::getSharedRef() { return shared_from_this(); }
class AManager {
static std::vector<std::shared_ptr<A>> aList;
public:
static void init(); // safety because statics
static void doLotsOfWork();
static std::shared_ptr<A> createA();
};
std::vector<std::shared_ptr<A>> AManager::aList;
void AManager::init() { aList = std::vector<std::shared_ptr<A>>{}; }
void AManager::doLotsOfWork() {
for (auto a : aList) {
a->doWork();
}
}
std::shared_ptr<A> AManager::createA() {
std::shared_ptr<A> a = std::make_shared<A>();
aList.push_back(a);
return a->getSharedRef(); // <----- EXCEPTION
}
int main() {
AManager::init();
AManager::createA();
return 0;
}
For some reason, this throws a std::bad_weak_ptr
, and upon inspection I notice that a
, for whatever reason, has an _M_weak_this
equal to 0x0
, or NULL
. Since I've already created a valid std::shared_ptr
referencing the object, it shouldn't be empty.
Furthermore, I know no memory corruption is occurring because A
(with variables) is completely intact at its address.
What am I doing wrong?
The problem appears to be because you are inheriting privately from enable_shared_from_this
shared_from_this
requires "enable_shared_from_this<T>
shall be an accessible base class of T
." (according to [util.smartptr.enab])
By inheriting privately, the base class is not accessible, and so the preconditions are violated. I presume this means undefined behavior. Both Clang and GCC throw an exception.
The solution is to inherit publicly.
class A : public std::enable_shared_from_this<A> {
//...
};
*In C++17 the wording appears to have moved to [util.smartptr.shared.const], but the requirement is basically the same.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With