Suppose I have a singleton class S in a static library, this could be linked with the other dynamic libraries D1 D2 D3,
So from what I understand the class S will have a separate instance in each D1, D2 and D3 and this would be true even if it is not a singleton (like global)
Is there any way to prevent multiple copies of class S? I cannot put the singleton S in another Dynamic library.
Executable
/ | \ \
D1 D2 D3 D4
| | |
S S S
EDIT:
The singleton S is in a separate static library that links with D1 D2 D3... separately.
The singleton is allocated in the heap, only the pointer is static
static s::instance()
{
static smart_ptr<S> ptr = NULL;
if(ptr == NULL) ptr = new S;
return ptr;
}
Edit2:
I made a simple test case to check things out This is a sample makefile (replace .dll by .so) i made to check things out, I checked it on Ubuntu and Cygwin, both g++ compilers and the behaviour was different. cygwin created 2 different objects but but ubuntu created 1 objects
all: dynamic1 dynamic2 main
static: static.cpp
g++ -c -fPIC static.cpp -o obj/static.o
ar rvs lib/static.a obj/static.o
dynamic1: static dynamic1.cpp
g++ -fPIC -shared dynamic1.cpp lib/static.a -o lib/libdynamic1.dll
dynamic2: static dynamic2.cpp
g++ -fPIC -shared dynamic2.cpp lib/static.a -o lib/libdynamic2.dll
main: dynamic1 dynamic2 main.cpp
g++ --std=c++11 main.cpp -ldynamic1 -ldynamic2 -o lib/main -L./lib
Singletons are well testable while a static class may not; If your class stores state (data), running multiple tests might effect each other, so writing test will be harder. Static classes are hard or impossible to mock. So, if you are testing a class depends on the static class, mocking may not be an easy option.
Suppose I have a singleton class S in a static library, this could be linked with the other dynamic libraries D1 D2 D3, So from what I understand the class S will have a separate instance in each D1, D2 and D3 and this would be true even if it is not a singleton (like global)
The Basics Let's hit ground zero. Singleton is a design pattern that assures a single instance of a Class for the lifetime of an application. It also provides a global point of access to that instance. static – a reserved keyword – is a modifier that makes instance variables as class variables.
Your code will be more flexible if you are using a singleton class and another advantage is that the code that uses the singleton does not need to know if it is a singleton object or a transient object. Using a static means you have to call static methods explicitly. Static classes also fail during dependency injection.
If your dynamic linker is not broken, you should not have any problems. Even if every dynamic library actually contains the object files from the static library S, the dynamic loader should be clever enough to determine that they correspond to the same symbol, and use consistently the same addresses throughout the whole application.
In short, if your system is not broken has a true dynamic loader, there is no problem here
Per your edit, I confirm that above is the way it should be in a nice world and the way it is in Unix-like systems. You say it works on Ubuntu, and I can confirm is works the same on FreeBSD.
But on Windows, it is unfortunately different. You do not have a true dynamic loader like ld.so
but you only require addresses of exported functions or data from the DLL. As a result, each DLL will use its own copy of the singleton, because each will contain its own copy of the code and use it because there is no global linking phase to merge that.
What is even worse is that I cannot imagine any simple workaround: static linking and dynamic linking have different behaviour full stop. That means that as soon as you use dynamic linking on Windows, a singleton or any shared data that can be accessed from at least two different DLLs must reside in a single place, meaning a DLL.
TL/DR: If your system has a real dynamic loader (Unix like have), you do not have to bother about static or dynamic linking, the loader (ld.so
) will care about it. On Windows, that has no dynamic loader but a run-time LoadLibrary
API call, any shared data must reside in one and only one module.
there are two case of implementation for the singletone.
1, single instance as a pointer, getInstance will dynamically allocate memory from heap in this case.
2, single instance as a static member and there is no memory allocation happens.
The following link discusses where is the static memory located: Where are static variables stored (in C/C++)?
In any of above implementation: If D1, D2, D3 and D4 are in same application and thus same process (e.g. used in different threads), then they share same singleton. If D1, D2, D3 and D4 are belong to different process, i.e. they have its own memory space and thus don't share same singleton.
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