Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Destructor for static fields. Singleton realization

So, classic simple Singleton realization is following:

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

cpp-file:

Singleton* Singleton::singleton = 0;

Singleton* Singleton::getInstance()
{
    if (!singleton)
    {
        singleton = new Singleton;
    }

    return singleton;
}

I see memory leak here - 'cos there is no delete for the new. But in C++ there isn't static destructor, so we just don't care about this memory leak?

like image 749
Hate Avatar asked Apr 01 '12 20:04

Hate


People also ask

Does a singleton need a destructor?

Having a private destructor as part of a singleton is not required from a programmer's point of view, but essential from a design point of view.

Can destructor be static C++?

Destructors cannot be declared const , volatile , const volatile or static . A destructor can be declared virtual or pure virtual . If no user-defined destructor exists for a class and one is needed, the compiler implicitly declares a destructor.

Can destructor be static?

No, there isn't. A static destructor supposedly would run at the end of execution of a process.


2 Answers

Why you should avoid such code, when there is no matching delete for new

While there is no actual memory leak (in most modern operating systems), worse thing is that your Singleton destructor doesn't get called. And if you acquire some resources, they propbably would leak.

What can be done here

Use smart pointer to store instance, consider std::unique_ptr (with C++11) or boost::auto_ptr

like image 23
Lol4t0 Avatar answered Oct 25 '22 07:10

Lol4t0


A memory leak is more than just an allocation with no matching free. It's when you have memory that could be reclaimed because the object is no longer in use, but which doesn't ever actually get freed. In fact, many memory leaks are cases where there is code in the program to deallocate memory, but for whatever reason it doesn't get called (for example, a reference cycle). There's a lot of research on how to detect these sorts of leaks; this paper is an excellent example of one such tool.

In the case of a singleton, we don't have a leak because that singleton exists throughout the program. Its lifetime is never intended to end, and so the memory not getting reclaimed isn't a problem.

That said, the code you have above is not how most people would implement a singleton. The canonical C++ implementation would be something like this:

class Singleton
{
private:
    /* No instantiation. */
    Singleton() {}

    /* Explicitly disallow copying. */ 
    Singleton(const Singleton&) = delete;
    Singleton& operator= (const Singleton&) = delete;

    /* In C++03, the above would be written as
     *
     *    Singleton(const Singleton&);
     *    Singleton& operator= (const Singleton&);
     * 
     * and you'd just leave the methods unimplemented.
     */
public:
    static Singleton& getInstance();        
};

.cpp file:

Singleton& Singleton::getInstance() {
    /* Have a static local variable representing the unique instance.  Since
     * it's static, there is only one instance of this variable.  It's also only
     * initialized when getInstance is called.
     */
    static Singleton theInstance;
    return theInstance;
}

Now there's no dynamic allocation at all - the memory is allocated by the compiler and probably resides in the code or data segment rather than in the heap. Also note that you have to explicitly disallow copying, or otherwise you could end up with many clones of the singleton.

The other advantage of this is that C++ guarantees that at program exit (assuming the program terminates normally), the destructor for theInstance will indeed fire at the end of the program. You can thus define a destructor with all the cleanup code you need.

Hope this helps!

like image 185
templatetypedef Avatar answered Oct 25 '22 05:10

templatetypedef