Leak-Free Singleton Class using auto_ptr


#include <memory>
#include <iostream>

using std::auto_ptr;

class MySingle
{
public:
static MySingle* Instance();
void SayHello() { std::cout << “Hello World!” << std::endl; }

private:
MySingle() {};
static auto_ptr<MySingle> sm_inst;
};


auto_ptr<MySingle> MySingle::sm_inst;

MySingle* MySingle::Instance()
{
if(sm_inst.get() == 0)
{
auto_ptr<MySingle> tmp(new MySingle);
sm_inst = tmp;
}
return sm_inst.get();
}

int main()
{
MySingle* pSing = MySingle::Instance();
if(pSing != 0)
{
pSing->SayHello();
}

return 0;
}


By Way of Explanation

The code is pretty much the same as the original except that the CSingleton
wrapper class has been removed and the sm_inst member is now of type
auto_ptr<>. <memory> was #include’d to give us access to auto_ptr.
The parts of code required to be added have been set in a bold font. Instead of
having our own CSingleton class we have simply added one static member and
one static method to the class we wish to make into a singleton. The auto_ptr
class is the class used to replace our CSingleton and comes provided as part
of the standard C++ library.

One code change was required in the Instance() method. This is due to the
fact that the auto_ptr class does not provide a set() method for its already
provided get() method. It does, however, provide an assignment operator. For
this reason it was necessary to introduce a temporary variable "tmp"
into the Instance method and construct it with a pointer to the allocated memory.
This pointer is then assigned to the already-constructed sm_inst auto_ptr which
takes over management of the pointer resource. Apart from that, the class
functions in much the same way as the previous version, so what is there to
choose between them?

The original required a wrapper class with a nested class and a couple of
methods defined to ensure a leak-free implementation. It also relied on the
fact that we would use the wrapped class and not the "bare" class
itself. If this is kept to then the first implementation is fine. However, for
each of your singleton classes you would need some way of duplicating the
resource protection provided by the nested InstPtr class and also an
agreement that all clients only use the wrapped version.

The version presented here has a more direct impact on the class you
wish to make into a singleton. The class itself becomes modified with the
addition of a static method (Instance) and a static member (sm_inst) – no
wrapper class is required. Thus the singleton behaviour will be enforced for
this class and an agreement to use any form of wrapper class is no longer
needed. Additionally, the nested class code to manage the resource has
already been coded into a standard available C++ class : auto_ptr. This saves
us defining our own class and helps in providing a more standard interface. I
for one prefer to use standard library components unless there is a good
reason not to.

The standard C++ library auto_ptr<> class supports the
"resource acquisition is initialisation" idiom. For more information
on this, section 14.4 in Bjarne Stroustrup’s book
"The C++ Programming Language"
may prove enlightening.

The auto_ptr class is a class which "manages" a pointer assigned
to it and which deallocates the pointer when the auto_ptr class goes out of
scope. This is precisely the functionality we wish to provide for our
singleton class.


Executable Checks

As per the original, I ran it through integrated Bounds Checker and got the following:

208 bytes _malloc_dbg leak

The 208 bytes leak may be attributable to Microsoft’s implementation of the
C++ standard library for iostream (see
A leak-free singleton class
for further details). The LCMapStringW problems are due to the C run-time
libraries and there’s not much we can do about those either. Perhaps the most
interesting thing to note is that the singleton class doesn’t leak – just like
the original.


Conclusions

This implementation of the singleton pattern provides the same functionality as
its predecessor and meets the original design goal of a leak-free implementation
of the singleton pattern. However, this version has notable code maintenance
benefits in that there is less user-defined code and a standard, pre-coded,
pre-tested C++ standard library component is used. This can only aid
readability, maintenance and program robustness.


References

Resource Management,
section 14.4, page 364,
"The C++ Programming Language 3rd Edition"
by Bjarne Stroustrup,
Publishers: Addison-Wesley,
ISBN 0-201-88954-4

More by Author

Must Read