2

Bring you two different implantation of singleton design pattern:

static class member

class SingletonCSM;
using SingletonCSMSp = std::shared_ptr < SingletonCSM > ;

class SingletonCSM
{
public:

    ~SingletonCSM()  { spInstance = nullptr; }

    static SingletonCSMSp GetInstance()
    {
        if (!spInstance)
            spInstance = std::make_shared<SingletonCSM>();

        return spInstance;
    }

private:

    SingletonCSM() {}

    // will be intilized in the cpp: SingletonCSMSp SingletonCSM::spInstance = nullptr;
    static SingletonCSMSp spInstance; 
};

static member variable

class SingletonFSV;
using SingletonFSVSp = std::shared_ptr < SingletonFSV > ;

class SingletonFSV
{
public:

    ~SingletonFSV() {}

    static SingletonFSVSp GetInstance()
    {
        static SingletonFSVSp spInstance = std::make_shared<SingletonFSV>();
        return spInstance;
    }

private:

    SingletonFSV() {}

};

I always use the first impl. SingletonCSM. I came across, in our code, an impl. like SingletonFSV

Questions

  1. Can we consider both impl. as a valid impl. of the design pattern?
  2. Are both, functionally, the same?

Motivation

Background

Class SingletonFSV was implemented as a part of a DLL project. This DLL, compiled in VS 2013, is loaded in memory by an exe file and run.

Problem

I've upgrade my VS to VS 2015, compiled the DLL project and run the exe. All of a sudden, it crashed. While debugging, I've notice that the crash happened in the DLL itself. make_shared called withing GetInstance() returned nullptr and naturally caused segmentation fault.

Solution

I've changed SingletonFSV impl. to SingletonCSM and the crash stopped. make_shared returned a valid pointer and the problem was solved.

Question

I just don't understand what was the problem and why was it solved?

6
  • You should not inline static SingletonFSVSp GetInstance() Commented Sep 21, 2016 at 12:44
  • Do note that neither of these are singletons. They both have public constructors meaning you can make as many instances as you want. Commented Sep 21, 2016 at 12:47
  • @DieterLücking is that related to the problem or just a general comment? 10x. Commented Sep 21, 2016 at 12:47
  • @NathanOliver correct I'll update the question Commented Sep 21, 2016 at 12:48
  • @idanshmu ... the static variable of that inline function (not put into a specific translation unit) is the problem. Commented Sep 21, 2016 at 13:05

1 Answer 1

2

When you put a static variable inside a function it is created the first time the function is called so it is guaranteed to have been instantiated to all callers of the function.

Members that are declared static could be instantiated before or after you call your function because the initialization order between translation units is undefined. So a global object or static object could try to access a static member before its been initialized by the runtime system.

So to your questions:

  1. Can we consider both impl. as a valid impl. of the design pattern?
  2. Are both, functionally, the same?

No. Using a static member is dangerous because a caller to SingletonCSM::GetInstance() can access a non-created object if the nullptr initialization has not taken place before the call. The static function method is the recommended method because it guarantees initialization has completed for every caller.

I just don't understand what was the problem and why was it solved?

In your case moving to the more dangerous method appears to have stopped your crash. I can not explain why that is. But you may not have removed the problem, it may be that you have undefined behavior elsewhere that has simply stopped manifesting in this case but that may resurface later with a different change.

Sign up to request clarification or add additional context in comments.

2 Comments

OK. but how does it explain the problem? I would expect SingletonFSV to work always while SingletonCSM may crash occasionally. but the problem is the other way around
@idanshmu Yes I can't answer your third question. I misread your problem and assumed the function static method solved it. This sounds like a job for your debugger because, in principle, using a static member is problematic and to be avoided whereas using a function static is considered the safe option.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.