使用共享指针访问单例子类时的SEGFAULT

时间:2015-02-12 08:02:03

标签: c++ inheritance segmentation-fault singleton shared-ptr

我有一个模板类ISingleton

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

父类和Parent的子类,它是一个单例

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将导致段错误。我无法弄清楚它是继承问题还是单例本身的实现。谢谢你的建议!

2 个答案:

答案 0 :(得分:1)

你做的不是C ++中被认为是单身的东西。单例永远不会被破坏和重新创建,因此将其存储在智能指针中是没有意义的。

但是如果你想用智能指针销毁它,你需要告诉智能指针如何做到这一点。默认情况下,智能指针会调用operator delete。您可以在operator delete中为其定义特定于类的ISingleton

void operator delete(void *me) noexcept
{
    // Possibly assert(me == mInstance);
    mInstance = nullptr;
    ::operator delete(me);
}

或者你可以提供带有lambda的智能指针,该lambda将调用destroy而不是delete

std::shared_ptr<Parent> module(Child::getInstance(),
        [](Parent*){ Child::destroy(); });

答案 1 :(得分:0)

你不应该将单个地址引入智能指针,因为它是拥有资源的单例。

如果您需要非拥有 shared_ptr,您可以使用空删除器:

std::shared_ptr<Parent> dummy_ptr(Child::getInstance(), [](Parent*){/*Nothing*/});

但是将方法更改为不shared_ptr似乎更好。