Question

I'm currently working on an application which heavily uses Singletons and Dynamic Libraries (using dlopen).
My problem is that the instance of my Singleton within the application AND within the dynamic library is different (i.e in my implementation, the Singleton::getInstance method returns a different address)

This is how I define a Singleton

// Singleton.hpp
template<typename T>
class                   Singleton
{
  static T              *_instance;

protected:
  Singleton<T>() {}
  virtual ~Singleton<T>() {}

public:
  static T              *getInstance() {
    if (_instance == NULL)
      _instance = new T;
    return (_instance);
  }

  static void           deleteInstance() {
    if (_instance) {
      delete _instance;
      _instance = NULL;
    }
  }
};

template<typename T>
T                       *Singleton<T>::_instance = NULL;

Then, if I want a class Test to be a Singleton, I need to do :

// Test.hh
#include                   "Singleton.hpp"

class                      Test : public Singleton<Test>
{
  friend class             Singleton<Test>;

private:
  Test();
public:
  virtual ~Test();

  void                     doSomeStuff();
};

Now if I want to use Test, I do :

#include                   "Test.hh"

int                        main() {
  Test                     *test = Test::getInstance();

  test->doSomeStuff();
  return (0);
}

To solve the problem, I tried to somehow " extern " (using the keyword) the static class member Singleton::_instance, but I never succeeded in compiling my application ... GCC refuses that kind of code (in the Singleton.hpp) file :

template<typename T>
extern T                   *Singleton<T>::_instance;
Was it helpful?

Solution

The following needs to be moved out of singleton.hpp. As written it creates an instance of the pointer for each .cpp file that includes singleton.hpp.

template<typename T>
T                       *Singleton<T>::_instance = NULL;

Remember that this is a definition, not a declaration. So every object file that includes your header is now defining Singleton::_instance. If multiple .cpp files include singleton.h and instantiate the template with the same type in a single target (executable or library) you'll get multiply defined symbols.

To make this code correct you'll need to pick a single .cpp file (in the client of the singleton template) and defined _instance there. This is obviously not super desirable, so consider not using a singleton (your first, best option) or using a different singleton pattern.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top