Does the Meyers Singleton work in a scenario with dynamic libraries?
I.e. one library defining the singleton, others using it, each in its own compilation unit?
(I suppose it doesn't matter but the specific architecture is an application with frameworks on OS X)
I'm using the vanilla Meyers Singleton pattern: The following Instance()
method is defined inline in the header file for a utility class (that's defined in a dynamic library):
static Logger& Instance()
{
static Logger singletonInstance;
return singletonInstance;
}
Copy constructor and operator=
are declared private and not implemented, so we should be good, right?
Now if I link that library defining the singleton from the main app I can see the constructor being called multiple times.. with different addresses for this
and all the weirdness I would expect when not having an actual singleton but multiple instances of the class.
So I'm wondering whether the dynamic library approach screws up the Meyers singleton or whether each compilation unit - library, main app - that includes the header for the singleton (effectively declaring and defining the Instance() method) will get "it's own singleton instance"?
Really not quite sure what to make of my observations so any hints much appreciated!
You need to declare Instance
in a header, and then define it in a dynamic library (presumably the same one that Logger
is defined in). And you need to drop the static
. And you need to make sure Instance
has default visibility if you are using the visibility tools.
From your description, it sounds like you've defined this function in a header. This would give everyone who includes the header their own private definition of Instance
, and thus their own private definition of the static Logger
within Instance
.
You could declare Instance
inline
, and that would give everything the semantics you expect (same as declaring in header and defining in the dylib). But my recommendation is to just do the inline to confirm what I'm telling you is correct (it is easy), and then outline into a dylib (and confirm again).
Once outlined, your design should work fine.
That being said, it is only guaranteed to work in C++11. That is, local statics are not thread safe in C++98/03, but are in C++11 and later. However, on OS X, they are thread safe even in C++03 language mode as an extension.
One other caveat: If you access Instance()
in the atexit chain (or in a destructor of a global object), it is possible that your access will occur after the destruction of the static local singletonInstance
within Instance()
, causing undefined behavior. If you don't register things with atexit()
, and if your global destructors don't call Instance()
, you're safe. Otherwise you aren't. If you aren't safe, you can purposefully leak it:
Logger& Instance()
{
static Logger* singletonInstance = new Logger;
return *singletonInstance;
}
This may cause some memory leak checkers to report false positives (or maybe they are true positives depending on your point of view), which is irritating.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With