Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Singleton: is there a memory leak?

This is a simple singleton:

class Singleton
{
    Singleton();
    virtual ~Singleton();

    Singleton * Singleton::getInstance() 
    {
        static Singleton * instance;

        if (!instance) {
            instance = new Singleton();
        };
        return instance;
    };
}

When main code calls Singleton::getInstance()->someMethod() for the first time, isn't the class instantiated twice? Will be there memory leak?

I am asking because Visual Leak Detector detects memory leak on the line with new Singleton().

like image 793
vladon Avatar asked Jun 02 '15 17:06

vladon


People also ask

Does singleton cause memory leak?

In other word, Singleton doesn't hold the activity context reference by calling the setString() method. Similarly, if the application class(the class extended from Android Application() ) holds a reference of an activity, or a fragment holds a reference of its views, both will cause a memory leak.

Why should we avoid singleton?

By using singletons in your project, you start to create technical debt. Singletons tend to spread like a virus because it's so easy to access them. It's difficult to keep track of where they're used and getting rid of a singleton can be a refactoring nightmare in large or complex projects.

Does a singleton stay in memory?

Singletons are references attached to classes, just as classes are global references these are not reached by the garbage collector. In case the Singleton is a complex object, this entire object, in addition to the transitive closure of all its references, will stay in memory throughout the execution.

Can singleton be destroyed?

The true, non monobehaviour singleton can't really be destroyed or reinitialized as the static field is read only. If you need this you have to do the usual singleton approach with a normal private static variable. To force a reinitialization you just add a method "Destroy" which sets the static reference to "null".


1 Answers

When main code calls Singleton::getInstance()->someMethod() for the first time, isn't the class instantiated twice?

No. Calling a static member of Singleton does not instantiate Singleton, so the only instance of Singleton to exist here is the one you create with new. And you only create it once, because once instance points to it, you never call new again.

One problem you have here, however, is that you failed to make getInstance a static member function. I assume this is a typo/oversight since, otherwise, your program would not even compile. In fact, the declaration is ill-formed even as a non-static member. Furthermore, the constructor should be private to enforce the notion that only getInstance may instantiate the type.

Will be there memory leak?

Yes, and this is what Leak Detector is reporting. However, it's minimal: the problem is that there is nothing to delete that singleton instance right before your program shuts down.

Frankly I wouldn't worry about it. This may be one of those rare times that a leak is acceptable, mostly because more than a "leak" it's just a one-time failure to de-allocate on process shutdown.

However, if you get rid of the pointer entirely then you can avoid both problems at the same time, since one of the last things your program does will be to destroy objects of static storage duration:

#include <iostream>

class Singleton
{
public:
    ~Singleton()  { std::cout << "destruction!\n"; }

    static Singleton& getInstance() 
    {
        static Singleton instance;
        return instance;
    }

    void foo() { std::cout << "foo!\n"; }

private:
    Singleton() { std::cout << "construction!\n"; }
};

int main()
{
    Singleton::getInstance().foo();
}

// Output:
//   construction!
//   foo!
//   destruction!

(live demo)

No need even for a pointer!

This has the added benefit that the entire function becomes inherently thread-safe, at least as of C++11.

like image 128
Lightness Races in Orbit Avatar answered Oct 22 '22 08:10

Lightness Races in Orbit