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



Comments

  • confused, lost, please help

    Posted by Legacy on 03/12/2001 12:00am

    Originally posted by: Danielle

    Paul,

    I read your article 'A Leak-Free Singleton Class' and
    I really like the article. I have one question I beg
    of you to help answer.

    You posted this code:

    #include <iostream>
    #include "Singleton.h" // CSingleton

    using namespace std;

    class OneOf
    {
    public:
    void SayHello()
    { cout << "Hello World!" << endl; }
    };

    typedef CSingleton<OneOf> tOneOf;
    tOneOf::InstPtr tOneOf::sm_ptr;

    int main()
    {
    OneOf* pOne = tOneOf::Instance();
    if(pOne != 0)
    {
    pOne->SayHello();
    }
    return 0;
    }

    The code works great. However, let's say I have
    another class and within that class I want to call the
    function SayHello(). So let's say I have this:

    #include "newclass.h"

    int main()
    {
    OneOf* pOne = tOneOf::Instance();
    if(pOne != 0)
    {
    pOne->SayHello();
    }

    CNewClass newClass;

    return 0;
    }

    class CNewClass
    {
    CNewClass::CNewClass();
    ~CNewClass::CNewClass();

    void newfunction();
    }

    CNewClass::CNewClass()
    {
    // how can I call SayHello right here?
    }

    ~CNewClass::CNewClass()
    {
    }

    void CNewClass::newfunction()
    {
    // how can I call SayHello right here?
    }

    How can I call SayHello in the constructor and
    newfunction(). I only want to call the class OneOf
    one time only, but I want to access it's functions in
    many different classes.

    Please, please, any response you can give me will be
    greatly appreciated.

    Sincerely,
    Danielle (an overworked graduate student)

    Reply
  • Problem with initializing 'auto_ptr<MySingle> MySingle::sm_inst'

    Posted by Legacy on 04/28/1999 12:00am

    Originally posted by: Stephan Rudlof

    I think there is an initializing problem in the code:
    
    

    -------
    ...

    auto_ptr<MySingle> MySingle::sm_inst;

    MySingle* MySingle::Instance(){
    if(sm_inst.get() == 0) {
    auto_ptr<MySingle> tmp(new MySingle);
    sm_inst = tmp; // ### here is the problem
    }
    return sm_inst.get();
    }
    ...
    -------

    In the case of using this singleton ***while constructing*** a non local object (before a call to main())in another compilation unit,
    it is not guaranteed, that the static class variable sm_inst is fully constructed at the time of this assignment.
    It's constructor could be called *after* the assignment.

    A solution would be to go to a heap variant, e.g. in
    http://codeguru.com/cpp_mfc/leakfree_singleton.shtml
    .


    Reply
  • A cleaner solution...

    Posted by Legacy on 04/06/1999 12:00am

    Originally posted by: Paul Miller

    You don't really need smart pointers to do singletons well.
    
    Just rely on normal static initialization and destruction
    to do it for you:

    class MySingleton
    {
    public:
    static MySingleton &Get()
    {
    static MySingleton singleton;
    return singleton;
    }

    void DoSomething() { ... }

    private:
    Singleton() { ... }
    };

    MySingleton::Get().DoSomething();

    Constructor is private so nobody is tempted to create one
    on the stack. Now the only way to get one is via the
    static Get() method, which statically initializes the
    object the first time it is called. The object gets
    destroyed in reverse order during program shut-down.

    Quite a bit cleaner.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • This paper introduces IBM Java on the IBM PowerLinux 7R2 server and describes IBM's implementation of the Java platform, which includes IBM's Java Virtual Machine and development toolkit.

  • A modern mobile IT strategy is no longer an option, it is an absolute business necessity. Today's most productive employees are not tied to a desk, an office, or a location. They are mobile. And your company's IT strategy has to be ready to support them with easy, reliable, 24/7 access to the business information they need, from anywhere in the world, across a broad range of communication devices. Here's how some of the nation's most progressive corporations are meeting the many needs of their mobile workers …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds