Discussion:
Singleton instantiated more than once with -fvisibility=hidden
Filipe Sousa
2005-06-03 10:25:44 UTC
Permalink
I have 3 files, the library (singleton.h/.cc) and the main program (main.cc)

-- singleton.h --
#pragma once

#include <iostream>

class singleton {
public:
singleton() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
static singleton* instance() {
static singleton s;
return &s;
}
};

-- singleton.cc --
#include "singleton.h"

void foo()
{
singleton::instance();
}

-- main.cc --
#include "singleton.h"

int main() {
foo();
singleton::instance();
return 0;
}

c++ -g -fPIC -Wall -c singleton.cc -o singleton.o
c++ -fPIC -shared -Wl,-soname,libsingleton.so -o libsingleton.so singleton.o
c++ -Wall -g -c main.cc -o main.o
c++ -g -fPIC main.o -o main -rdynamic -L${PWD} -lsingleton -Wl,-rpath,${PWD}

***@neptuno ~/tmp/vis $ ./main
singleton::singleton()

Here, the singleton is only instanciated once as expected, but if I add
visibility support to the code

-- singleton.h --
#pragma once

#include <iostream>

class __attribute__ ((visibility("default"))) singleton {
public:
singleton() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
static singleton* instance() {
static singleton s;
return &s;
}
};

__attribute__ ((visibility("default"))) void foo();

c++ -g -fPIC -Wall -fvisibility-inlines-hidden -fvisibility=hidden -c
singleton.cc -o singleton.o
c++ -fPIC -fvisibility-inlines-hidden -fvisibility=hidden -shared
-Wl,-soname,libsingleton.so -o libsingleton.so singleton.o
c++ -Wall -g -c main.cc -o main.o
c++ -g -fPIC main.o -o main -rdynamic -L${PWD} -lsingleton -Wl,-rpath,${PWD}

***@neptuno ~/tmp/vis $ ./main
singleton::singleton()
singleton::singleton()

I have more than one instance. Am I doing something wrong?

gcc (GCC) 4.0.1-beta20050526 (Gentoo 4.0.1_beta20050526)

-- Filipe Sousa
Mws
2005-06-03 10:29:41 UTC
Permalink
imho this is not how to use a singleton at all.
think about what you do.
Post by Filipe Sousa
I have 3 files, the library (singleton.h/.cc) and the main program (main.cc)
-- singleton.h --
#pragma once
#include <iostream>
class singleton {
singleton() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
static singleton* instance() {
static singleton s;
return &s;
}
};
-- singleton.cc --
#include "singleton.h"
void foo()
{
singleton::instance();
}
-- main.cc --
#include "singleton.h"
int main() {
foo();
singleton::instance();
return 0;
}
c++ -g -fPIC -Wall -c singleton.cc -o singleton.o
c++ -fPIC -shared -Wl,-soname,libsingleton.so -o libsingleton.so singleton.o
c++ -Wall -g -c main.cc -o main.o
c++ -g -fPIC main.o -o main -rdynamic -L${PWD} -lsingleton -Wl,-rpath,${PWD}
singleton::singleton()
Here, the singleton is only instanciated once as expected, but if I add
visibility support to the code
-- singleton.h --
#pragma once
#include <iostream>
class __attribute__ ((visibility("default"))) singleton {
singleton() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
static singleton* instance() {
static singleton s;
return &s;
}
};
__attribute__ ((visibility("default"))) void foo();
c++ -g -fPIC -Wall -fvisibility-inlines-hidden -fvisibility=hidden -c
singleton.cc -o singleton.o
c++ -fPIC -fvisibility-inlines-hidden -fvisibility=hidden -shared
-Wl,-soname,libsingleton.so -o libsingleton.so singleton.o
c++ -Wall -g -c main.cc -o main.o
c++ -g -fPIC main.o -o main -rdynamic -L${PWD} -lsingleton -Wl,-rpath,${PWD}
singleton::singleton()
singleton::singleton()
I have more than one instance. Am I doing something wrong?
gcc (GCC) 4.0.1-beta20050526 (Gentoo 4.0.1_beta20050526)
-- Filipe Sousa
Filipe Sousa
2005-06-03 12:39:53 UTC
Permalink
Post by Mws
imho this is not how to use a singleton at all.
think about what you do.
I don't see any problem, could you please be elaborate?
Post by Mws
Post by Filipe Sousa
I have 3 files, the library (singleton.h/.cc) and the main program (main.cc)
-- singleton.h --
#pragma once
#include <iostream>
class singleton {
singleton() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
static singleton* instance() {
static singleton s;
return &s;
}
};
-- singleton.cc --
#include "singleton.h"
void foo()
{
singleton::instance();
}
-- main.cc --
#include "singleton.h"
int main() {
foo();
singleton::instance();
return 0;
}
c++ -g -fPIC -Wall -c singleton.cc -o singleton.o
c++ -fPIC -shared -Wl,-soname,libsingleton.so -o libsingleton.so
singleton.o c++ -Wall -g -c main.cc -o main.o
c++ -g -fPIC main.o -o main -rdynamic -L${PWD} -lsingleton
-Wl,-rpath,${PWD}
singleton::singleton()
Here, the singleton is only instanciated once as expected, but if I add
visibility support to the code
-- singleton.h --
#pragma once
#include <iostream>
class __attribute__ ((visibility("default"))) singleton {
singleton() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
static singleton* instance() {
static singleton s;
return &s;
}
};
__attribute__ ((visibility("default"))) void foo();
c++ -g -fPIC -Wall -fvisibility-inlines-hidden -fvisibility=hidden -c
singleton.cc -o singleton.o
c++ -fPIC -fvisibility-inlines-hidden -fvisibility=hidden -shared
-Wl,-soname,libsingleton.so -o libsingleton.so singleton.o
c++ -Wall -g -c main.cc -o main.o
c++ -g -fPIC main.o -o main -rdynamic -L${PWD} -lsingleton
-Wl,-rpath,${PWD}
singleton::singleton()
singleton::singleton()
I have more than one instance. Am I doing something wrong?
gcc (GCC) 4.0.1-beta20050526 (Gentoo 4.0.1_beta20050526)
-- Filipe Sousa
--
Filipe Sousa
Mws
2005-06-03 12:46:33 UTC
Permalink
hi,

in my understanding a singleton is used to have a class
instanciated only for one time.

normally this is done by

having the "wanted-to-be-singleton-class" derived/inherited from
a singleton class or template.
never ever from the outside ctors are called, but there should be
a getInstance() method that checks for _m_instance == NULL
if it is matching creating a new instance with new, otherwise returning the _m_instance pointer.

if you want to, i can provide you with a complete singleton template.

regards
mws
Post by Filipe Sousa
Post by Mws
imho this is not how to use a singleton at all.
think about what you do.
I don't see any problem, could you please be elaborate?
Post by Mws
Post by Filipe Sousa
I have 3 files, the library (singleton.h/.cc) and the main program (main.cc)
-- singleton.h --
#pragma once
#include <iostream>
class singleton {
singleton() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
static singleton* instance() {
static singleton s;
return &s;
}
};
-- singleton.cc --
#include "singleton.h"
void foo()
{
singleton::instance();
}
-- main.cc --
#include "singleton.h"
int main() {
foo();
singleton::instance();
return 0;
}
c++ -g -fPIC -Wall -c singleton.cc -o singleton.o
c++ -fPIC -shared -Wl,-soname,libsingleton.so -o libsingleton.so
singleton.o c++ -Wall -g -c main.cc -o main.o
c++ -g -fPIC main.o -o main -rdynamic -L${PWD} -lsingleton
-Wl,-rpath,${PWD}
singleton::singleton()
Here, the singleton is only instanciated once as expected, but if I add
visibility support to the code
-- singleton.h --
#pragma once
#include <iostream>
class __attribute__ ((visibility("default"))) singleton {
singleton() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
static singleton* instance() {
static singleton s;
return &s;
}
};
__attribute__ ((visibility("default"))) void foo();
c++ -g -fPIC -Wall -fvisibility-inlines-hidden -fvisibility=hidden -c
singleton.cc -o singleton.o
c++ -fPIC -fvisibility-inlines-hidden -fvisibility=hidden -shared
-Wl,-soname,libsingleton.so -o libsingleton.so singleton.o
c++ -Wall -g -c main.cc -o main.o
c++ -g -fPIC main.o -o main -rdynamic -L${PWD} -lsingleton
-Wl,-rpath,${PWD}
singleton::singleton()
singleton::singleton()
I have more than one instance. Am I doing something wrong?
gcc (GCC) 4.0.1-beta20050526 (Gentoo 4.0.1_beta20050526)
-- Filipe Sousa
Filipe Sousa
2005-06-03 13:09:00 UTC
Permalink
Post by Mws
hi,
in my understanding a singleton is used to have a class
instanciated only for one time.
normally this is done by
having the "wanted-to-be-singleton-class" derived/inherited from
a singleton class or template.
never ever from the outside ctors are called, but there should be
a getInstance() method that checks for _m_instance == NULL
if it is matching creating a new instance with new, otherwise returning the
_m_instance pointer.
A templated version

template<class T>
class singleton {
public:
static T* instance() {
if (!m_instance)
m_instance = new T;
return m_instance;
}

private:
static __attribute__ ((visibility("default"))) T* m_instance;
};

class __attribute__ ((visibility("default"))) my_singleton : public
singleton<my_singleton> {
public:
my_singleton() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
Post by Mws
if you want to, i can provide you with a complete singleton template.
Yes, please
Post by Mws
regards
mws
--
Filipe Sousa
Mws
2005-06-03 13:22:28 UTC
Permalink
Post by Filipe Sousa
Post by Mws
hi,
in my understanding a singleton is used to have a class
instanciated only for one time.
normally this is done by
having the "wanted-to-be-singleton-class" derived/inherited from
a singleton class or template.
never ever from the outside ctors are called, but there should be
a getInstance() method that checks for _m_instance == NULL
if it is matching creating a new instance with new, otherwise returning the
_m_instance pointer.
A templated version
template<class T>
class singleton {
static T* instance() {
if (!m_instance)
m_instance = new T;
return m_instance;
}
static __attribute__ ((visibility("default"))) T* m_instance;
};
class __attribute__ ((visibility("default"))) my_singleton : public
singleton<my_singleton> {
my_singleton() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
Post by Mws
if you want to, i can provide you with a complete singleton template.
Yes, please
Post by Mws
regards
mws
singleton.h

#ifndef __singleton__
#define __singleton__

template<class IMPLEMENTINGCLASS>
class TSingleton
{
private:
static IMPLEMENTINGCLASS* instance;

public:
static IMPLEMENTINGCLASS* getInstance()
{
//debugging purposes
std::cout << "before" << instance << std::endl;
if(!instance)
{
instance = new IMPLEMENTINGCLASS();
}
std::cout << "after" << instance << std::endl;
return instance;
}

void dispose()
{
if(instance)
{
delete instance;
instance = NULL;
}
}
};

template<class IMPLEMENTINGCLASS> IMPLEMENTINGCLASS* TSingleton<IMPLEMENTINGCLASS>::instance = NULL;

#endif

usage is like

class CFoo:public TSingleton<foo>
{
private:
CFoo();
virtual ~CFoo();

public:

...
...

};

in case of debugging this you should do a std::cout << instance << std::endl;
instead of mentioning that the ctor is called.


int main() {
// get the instance
CFoo::getInstance();
CFoo::getInstance();

// free mem - call dtor
CFoo::dispose();

return 0;
}

that's what i would do

regards
mws
Filipe Sousa
2005-06-03 13:45:35 UTC
Permalink
Post by Mws
template<class IMPLEMENTINGCLASS>
class TSingleton
{
                static IMPLEMENTINGCLASS* instance;
                static IMPLEMENTINGCLASS* getInstance()
                {
                        //debugging purposes
                        std::cout << "before" << instance << std::endl;
                        if(!instance)
                        {
                                instance = new IMPLEMENTINGCLASS();
                        }
                        std::cout << "after" << instance << std::endl;
                        return instance;
                }
                void dispose()
                {
                        if(instance)
                        {
                                delete instance;
                                instance = NULL;
                        }
                }
};
template<class IMPLEMENTINGCLASS> IMPLEMENTINGCLASS*
TSingleton<IMPLEMENTINGCLASS>::instance = NULL;
But I still have more then one instance:

before0
my_singleton::my_singleton()
after0x804a008
before0
my_singleton::my_singleton()
after0x804a018
--
Filipe Sousa
Mws
2005-06-03 14:09:51 UTC
Permalink
Post by Filipe Sousa
Post by Mws
template<class IMPLEMENTINGCLASS>
class TSingleton
{
                static IMPLEMENTINGCLASS* instance;
                static IMPLEMENTINGCLASS* getInstance()
                {
                        //debugging purposes
                        std::cout << "before" << instance << std::endl;
                        if(!instance)
                        {
                                instance = new IMPLEMENTINGCLASS();
                        }
                        std::cout << "after" << instance << std::endl;
                        return instance;
                }
                void dispose()
                {
                        if(instance)
                        {
                                delete instance;
                                instance = NULL;
                        }
                }
};
template<class IMPLEMENTINGCLASS> IMPLEMENTINGCLASS*
TSingleton<IMPLEMENTINGCLASS>::instance = NULL;
before0
my_singleton::my_singleton()
after0x804a008
before0
my_singleton::my_singleton()
after0x804a018
what?
s
Filipe Sousa
2005-06-03 14:20:10 UTC
Permalink
Post by Filipe Sousa
Post by Mws
template<class IMPLEMENTINGCLASS>
class TSingleton
{
                static IMPLEMENTINGCLASS* instance;
                static IMPLEMENTINGCLASS* getInstance()
                {
                        //debugging purposes
                        std::cout << "before" << instance << std::endl;
                        if(!instance)
                        {
                                instance = new IMPLEMENTINGCLASS();
                        }
                        std::cout << "after" << instance << std::endl;
                        return instance;
                }
                void dispose()
                {
                        if(instance)
                        {
                                delete instance;
                                instance = NULL;
                        }
                }
};
template<class IMPLEMENTINGCLASS> IMPLEMENTINGCLASS*
TSingleton<IMPLEMENTINGCLASS>::instance = NULL;
before0
my_singleton::my_singleton()
after0x804a008
before0
my_singleton::my_singleton()
after0x804a018
what?
show me your main please
regards
mws
--
Filipe Sousa
Martin York
2005-06-03 14:52:41 UTC
Permalink
There are many ways to implement the Singleton Pattern. Each has their
own positives and negatives. I would advice looking at "Scott Meyers"
book "More Effective C++"
http://www.amazon.co.uk/exec/obidos/ASIN/020163371X/ref=pd_bxgy_text_2_c
p/026-5023597-8506032


Personally I prefer being as simple as possible (Like your original
code).



The only problem with your original code is that

singleton* singleton::instance()

is defined in the header file. Therefore the implementation of instance
is not in the resulting shared library.

If you move the definition into the file singleton.cc then I believe
(though not tested) that your problem will be resolved.


As a secondary question/comment. Why return a pointer. To me this
implies it can fail and return a NULL (and thus needs to be checked). I
(personally) would return a reference.


singleton.cc

singleton& singleton::instance()
{
static singleton myInstance;
return(myInstance);
}

There is a small caveat to implementing the singleton this way. The
problem of the singleton being used by another singleton (that is
created before this one) in its destructor. [I'll let you think about
why that is a problem] Solutions to this and other problem are discussed
in "Scott Meyers" book.

PS. Because C++ automatically defines certain methods and to make sure
no other copies of a singleton can be created the following methods
should be defined as private:

class singleton
{
public:
singleton& instance();
private:
singleton(); // provide definition
~singleton(); // provide definition

/*
* The following methods should be declared so that the
compiler
* does not generate default implementations of them.
* But as they will never be used you do not need to actually
define them.
*/
singleton(const singleton& copy); // No definition
required.
singleton& operator=(const singleton& copy); // No definition
required.
};
Filipe Sousa
2005-06-03 15:16:52 UTC
Permalink
I'm aware of Singleton Pattern, my original code is a very simplistic
implementation to show my problem.

The point here is not about the quality of the pattern but the number of
instances when using these flags: -fvisibility=hidden
-fvisibility-inlines-hidden and __attribute__ ((visibility("default")))

Of course if I don't use these flags I only have one instance.
Post by Martin York
There are many ways to implement the Singleton Pattern. Each has their
own positives and negatives. I would advice looking at "Scott Meyers"
book "More Effective C++"
http://www.amazon.co.uk/exec/obidos/ASIN/020163371X/ref=pd_bxgy_text_2_c
p/026-5023597-8506032
Personally I prefer being as simple as possible (Like your original
code).
The only problem with your original code is that
singleton* singleton::instance()
is defined in the header file. Therefore the implementation of instance
is not in the resulting shared library.
If you move the definition into the file singleton.cc then I believe
(though not tested) that your problem will be resolved.
Can I move templated code to the implementation file? I thought that templated
code should be written in the declaration file.
Post by Martin York
As a secondary question/comment. Why return a pointer. To me this
implies it can fail and return a NULL (and thus needs to be checked). I
(personally) would return a reference.
[...]
--
Filipe Sousa
Loading...