使用共享指针访问单例 child class 时出现 SEGFAULT
SEGFAULT when accessing a singleton child class with shared pointer
我有模板classISingleton
class ISingleton
{
public:
static T* getInstance()
{
lock_guard<mutex> guard(mMutex);
if (mInstance == NULL)
{
mInstance = new T();
}
return mInstance;
}
static void destroy()
{
lock_guard<mutex> guard(mMutex);
delete mInstance;
mInstance = NULL;
}
ISingleton(ISingleton const&) = delete;
ISingleton& operator =(ISingleton const&) = delete;
protected:
ISingleton()
{
}
virtual ~ISingleton()
{
}
private:
static T* mInstance;
static mutex mMutex;
};
a parent class 和 Parent
的 child class 是单例
class Parent
{
public:
Parent(string name) { mName = name; }
virtual ~Parent();
string getName(){ return mName; }
private:
string mName;
}
class Child : public Parent, public ISingleton<Child>
{
public:
virtual ~Child();
private:
Child() { mName = "child"; }
friend ISingleton<Child>;
};
然后我像这样创建一个指向单例的共享指针
void foo()
{
shared_ptr<Parent> module(Child::getInstance());
}
Parent *c = Child::getInstance();
c->getName(); //SEGFAULT
如果 shared_ptr'
的引用计数达到零,就会出现问题。下一次调用 Child::getName
将导致段错误。我无法弄清楚这是继承问题还是单例本身的实现问题。谢谢指教!
你做的不是C++中的单例。单例永远不会被销毁和重新创建,因此将其存储在智能指针中毫无意义。
但是如果你想用智能指针销毁它,你需要告诉智能指针如何去做。默认情况下,智能指针调用operator delete
。您可以在 ISingleton
:
中定义 class-specific operator delete
void operator delete(void *me) noexcept
{
// Possibly assert(me == mInstance);
mInstance = nullptr;
::operator delete(me);
}
或者您可以为智能指针提供一个将调用 destroy
而不是 delete
的 lambda:
std::shared_ptr<Parent> module(Child::getInstance(),
[](Parent*){ Child::destroy(); });
您不应该将单例地址添加到智能指针中,因为它是拥有资源的单例。
因为你需要一个非拥有 shared_ptr
,你可以使用一个空的删除器:
std::shared_ptr<Parent> dummy_ptr(Child::getInstance(), [](Parent*){/*Nothing*/});
但将方法更改为不使用 shared_ptr
似乎更好。
我有模板classISingleton
class ISingleton
{
public:
static T* getInstance()
{
lock_guard<mutex> guard(mMutex);
if (mInstance == NULL)
{
mInstance = new T();
}
return mInstance;
}
static void destroy()
{
lock_guard<mutex> guard(mMutex);
delete mInstance;
mInstance = NULL;
}
ISingleton(ISingleton const&) = delete;
ISingleton& operator =(ISingleton const&) = delete;
protected:
ISingleton()
{
}
virtual ~ISingleton()
{
}
private:
static T* mInstance;
static mutex mMutex;
};
a parent class 和 Parent
的 child class 是单例
class Parent
{
public:
Parent(string name) { mName = name; }
virtual ~Parent();
string getName(){ return mName; }
private:
string mName;
}
class Child : public Parent, public ISingleton<Child>
{
public:
virtual ~Child();
private:
Child() { mName = "child"; }
friend ISingleton<Child>;
};
然后我像这样创建一个指向单例的共享指针
void foo()
{
shared_ptr<Parent> module(Child::getInstance());
}
Parent *c = Child::getInstance();
c->getName(); //SEGFAULT
如果 shared_ptr'
的引用计数达到零,就会出现问题。下一次调用 Child::getName
将导致段错误。我无法弄清楚这是继承问题还是单例本身的实现问题。谢谢指教!
你做的不是C++中的单例。单例永远不会被销毁和重新创建,因此将其存储在智能指针中毫无意义。
但是如果你想用智能指针销毁它,你需要告诉智能指针如何去做。默认情况下,智能指针调用operator delete
。您可以在 ISingleton
:
operator delete
void operator delete(void *me) noexcept
{
// Possibly assert(me == mInstance);
mInstance = nullptr;
::operator delete(me);
}
或者您可以为智能指针提供一个将调用 destroy
而不是 delete
的 lambda:
std::shared_ptr<Parent> module(Child::getInstance(),
[](Parent*){ Child::destroy(); });
您不应该将单例地址添加到智能指针中,因为它是拥有资源的单例。
因为你需要一个非拥有 shared_ptr
,你可以使用一个空的删除器:
std::shared_ptr<Parent> dummy_ptr(Child::getInstance(), [](Parent*){/*Nothing*/});
但将方法更改为不使用 shared_ptr
似乎更好。