I've found multiple posts describing in detail the differences between static and shared libraries; however, I have yet to see an overarching view on when the shared library is loaded, what goes on here, and when the library is unloaded. Especially how this is affected by the presence of static variables. I understand this differs from system to system but let's say on Linux.
1 Answers
Static linking - the code is linked directly into the executable program's file. The code effectively loads when the executable program is started. The loader doesn't really know about libraries at this point. All the addresses to invoked functions are resolved at compile/link time.
shared library loading (implicit linking). The code is compiled to link with the stub library (.sa file). When the executable program is started, the loader will need to interrogate the program to find out all its runtime library dependencies, resolve each's location (the .so file), do the position independent code fixups, update the symbol table, etc... That is, when the shared library is pulled into memory, there's some fixups on the addresses in which each function exists at. On linux, there's a common program called ldd
that will dump the list of .so file dependencies a program needs at runtime. The loader is effectively doing the equivalent of what ldd
does before loading the libraries into user space. Typically, the C/C++ runtimes and most system libraries (posix functions) are loaded this way.
Static/global variables are in a different part of the shared library and are duplicated by the loader for each process that loads the shared library.
shared library load (explicitly linking). The code invokes the dlopen library function to explicitly load a shared library (.so file) at runtime and invokes dlsym to get the address of a function inside that library so it can explicitly execute it. The loader does effectively the same thing as implicit loading, but doesn't pull the code into memory until the dlopen call.
Advantages of shared libraries include smaller executable program files and the shared libraries can be mapped into memory just once and shared among multiple programs running at the same time.
Windows has effectively the same pattern with DLLs. dumpbin.exe
is the equivalent tool to ldd
on Unix. LoadLibrary
and GetProcAddress
are the Windows equivalent to dlopen
and dlsym
.

- 100,020
- 15
- 103
- 173
-
From a `.so` file, is there a way to tell if the dependencies listed in ldd are implicit or explicitly linked? Additionally, so 2 processes that use the same shared library create 2 copies of the static variables present? Taking this one step further, given a program A that links to lib B (which contains static variables) both statically and dynamically (say A->B statically, C->B dynamically, and A-C dynamically). My understanding is that there will be 2 copies of the static variables, and when C is no longer needed, it unloads itself and the destructs one copy of those in it's linking to B. – Anthony Lam Jan 04 '22 at 09:05
-
`ldd` can only list link time (implicit) dependencies. There's no easy way to know if a piece of code is invoking `ldopen` on a specific runtime library or not. – selbie Jan 04 '22 at 17:35
-
The issue with your A/B/C example is that implies there is both static and a dynamic version of the library available. Uncommon in most build environment, but it's not unusual though. `A` would links with `b.a` and `c.sa`. C links with `b.sa`. Assuming no duplicate symbol warnings at link time, then you are correct with the variable count and lifetime. – selbie Jan 04 '22 at 17:44