0
#include <iostream>

class demo1
{
public:
    demo1();
};

class Singleton
{
private:
    Singleton();
public:
    static Singleton* getInstance();
};

Singleton* Singleton::getInstance()
{
    static Singleton s;
    return &s;
}

Singleton::Singleton() 
{
    demo1 d1;
}

demo1::demo1()
{
    Singleton::getInstance();
}

int main()
{
    std::cout << "vs2017 begin" << std::endl;
    Singleton::getInstance();
    std::cout << "vs2017 end" << std::endl;
}

visual studio 2017 not responding But can run in visual studio 2005

This project is a problem that arises when VS2005 is upgraded to vs2017. I'm curious why it can be done in VS2005

visual studio 2005 visual studio 2017

ClearSeve
  • 11
  • 1
  • 2
    _Why_ do you want to call `getInstance` in the constructor? – tkausl Feb 08 '22 at 01:54
  • If the constructor needs to refer to the Singleton instance during construction, you can just use `this`. By the definition of a Singleton, it must be the singleton instance that is being constructed. – François Andrieux Feb 08 '22 at 01:56
  • This project is a problem that arises when VS2005 is upgraded to vs2017. I'm curious why it can be done in VS2005 – ClearSeve Feb 08 '22 at 01:58
  • It can be done "by accident". This should never be done. The first time you enter `getInstance`, a lock is taken, the second time you enter you block on the lock. Or not, as seen in VS2005, but thats pure accident. – tkausl Feb 08 '22 at 02:00
  • It will be 100% implemented in VS2005, which makes me very confused – ClearSeve Feb 08 '22 at 02:05
  • 1
    Recursively passing the declaration while construction of the object is in progress in the same thread causes undefined behavior, see https://eel.is/c++draft/stmt.dcl#3. If it worked beforehand it was just luck. – user17732522 Feb 08 '22 at 02:08

1 Answers1

1

You have initialization recursion since your getInstance() function uses the constructor to create an object which then calls getInstance().

Dynamic initialization of a block variable with static storage duration or thread storage duration is performed the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. [...] If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.

"Working in VS2005" is one possible outcome of undefined behavior.

In this case, your constructor doesn't need to do anything and then everything will be ok:

Singleton::Singleton() = default;

Out of scope of the question: I suggest that you return the instance by reference instead. It makes integrating with most other code easier:

Singleton& Singleton::getInstance()
{
    static Singleton s;
    return s;
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • `You have infinite recursion` Actually, you don't, "Meyers Singletons" are initialized exactly once, the Standard guarantees this. The second entry to `getInstance` is probably UB either way as the lock is already held by the current thread, I'm not sure whether the Standard says anything about reentry of such functions containing a Meyers Singleton, – tkausl Feb 08 '22 at 02:03
  • It will be 100% implemented in VS2005, which makes me very confused – ClearSeve Feb 08 '22 at 02:04
  • I reworded it a bit - being a bit more careful about "infinite" etc. – Ted Lyngmo Feb 08 '22 at 02:39
  • @ClearSeve Visual Studio 2005 is too old to give multithreaded protection, so you're probably getting recursion. If you have the opportunity, you should consider upgrading from the compiler equivalent of a bronze-tipped spear. – user4581301 Feb 08 '22 at 03:28