dynamically loading static library?
A static library is more or less just a collection of object files. If you want to use a static library in a program, you have to link the executable with it. The executable will then contain the static library (or the parts that you used).
If you want to load a static library at runtime using dlopen
, you will have to first create a dynamic library libfoo.so
containing it.
Is the static loading of shared libraries linked like dynamic loading or static linking?
When you do static loading and dynamic linking of a shared library
You don't do 'static loading' of a shared library.
Even though it looks to you as an end-user that e.g. libc.so.6
is 'static loaded' at process startup, it is not in fact the case. Rather, the kernel 'static loads' the main binary and ld-linux.so
, and then ld-linux
dynamic loads all the other shared libraries.
does this linking patch my binary's references like in the static loading & linking scenario, or does it work by way of function pointers like in the case of dynamic loading
It depends.
Usually shared libraries are linked from position-independent code (PIC
), and work the way of function pointers (the pointers are stored in the GOT
-- global offset table).
But sometimes shared libraries are linked from non-PIC
code, and require "text relocations", which work similar to "static linking".
Why cant you statically link dynamic libraries?
Why is this the case?
Most linkers (AIX linker is a notable exception) discard information in the process of linking.
For example, suppose you have foo.o
with foo
in it, and bar.o
with bar
in it. Suppose foo
calls bar
.
After you link foo.o
and bar.o
together into a shared library, the linker merges code and data sections, and resolves references. The call from foo
to bar
becomes CALL $relative_offset
. After this operation, you can no longer tell where the boundary between code that came from foo.o
and code that came from bar.o
was, nor the name that CALL $relative_offset
used in foo.o
-- the relocation entry has been discarded.
Suppose now you want to link foobar.so
with your main.o
statically, and suppose main.o
already defines its own bar
.
If you had libfoobar.a
, that would be trivial: the linker would pull foo.o
from the archive, would not use bar.o
from the archive, and resolve the call from foo.o
to bar
from main.o
.
But it should be clear that none of above is possible with foobar.so
-- the call has already been resolved to the other bar
, and you can't discard code that came from bar.o
because you don't know where that code is.
On AIX it's possible (or at least it used to be possible 10 years ago) to "unlink" a shared library and turn it back into an archive, which could then be linked statically into a different shared library or a main executable.
If
foo.o
andbar.o
are linked into afoobar.so
, wouldn't it make sense that the call fromfoo
tobar
is always resolved to the one inbar.o
?
This is one place where UNIX shared libraries work very differently from Windows DLLs. On UNIX (under common conditions), the call from foo
to bar
will resolve to the bar
in main executable.
This allows one to e.g. implement malloc
and free
in the main a.out
, and have all calls to malloc
use that one heap implementation consistently. On Windows you would have to always keep track of "which heap implementation did this memory come from".
The UNIX model is not without disadvantages though, as the shared library is not a self-contained mostly hermetic unit (unlike a Windows DLL).
Why would you want to resolve it to another
bar
frommain.o
?
If you don't resolve the call to main.o
, you end up with a totally different program, compared to linking against libfoobar.a
.
segfault after linking static library into both exe and shared lib
So it seems like there are two copies of the global static variable?
Yes, that is expected.
Shouldn't the executable override the symbol from shared library so there is only one global static variable in the executable during dynamic linking?
A static
variable by definition has local linkage -- it is not accessible from any other compilation unit, and is not exported from the shared library(ies).
You would have to make this variable (and any other similar variables) non-static and exported from both shared libraries. Only then will the dynamic loader bind all references to this variable to a single instance.
Note that linking separate copies of libglib-2.0.a
into shared libraries without controlling symbol visibility is asking for trouble. Whatever you hoped to achieve by doing that, you are not achieving.
there is another executable that does the same as above, which seems to behave okay
Ah, programming by coincidence. The mine you stepped on didn't explode, so it should be ok to continue doing that.
Related Topics
Qtextedit with Different Text Colors (Qt/C++)
How to Prevent Screen-Savers and Sleeps During My Program Execution
How to Get Size of Check and Gap in Check Box
How to Resize an Image to a Specific Size in Opencv
Using Memory Sanitizer with Libstdc++
How to Sort C++ Array in Asc and Desc Mode
How to Add Code at the Entry of Every Function
In C++, Is a Function Automatically Virtual If It Overrides a Virtual Function
Using Std::Variant with Recursion, Without Using Boost::Recursive_Wrapper
Why Double Can Store Bigger Numbers Than Unsigned Long Long
How to Implement a Video Widget in Qt That Builds Upon Gstreamer
Catching Signals: Use a Member Function as Signal Handler
C++11 Random Number Distributions Are Not Consistent Across Platforms -- What Alternatives Are There
Under What Circumstances Is It Advantageous to Give an Implementation of a Pure Virtual Function
Heapcreate, Heapalloc in Linux, Private Allocator for Linux
G++ Can't Find Boost Libraries. I Say They'Re in Plain Sight
Read and Write on Serial Port in Ubuntu with C/C++ and Libserial