Static and Dynamic Linking, Shared Libraries
This chapter contrasts static and dynamic linking, and explains shared libraries: how they are built, loaded, and resolved.
Why This Matters
Whether a program links statically or dynamically affects its size, portability, startup time, memory footprint, and security (ASLR, library updates). This is a fundamental build and deployment decision.
Prerequisites
c.build.2— symbols, relocations, sections.
Core Concept
Static linking
The linker copies the needed library code into the executable. The result is self-contained but larger, and it cannot benefit from shared library updates.
Dynamic linking
The executable records a dependency on a shared library; the actual code is loaded and linked at run time by the dynamic loader. The result is smaller, and multiple processes can share one copy of the library in memory.
Examples
Static vs. dynamic (GCC/Clang)
# dynamic (default)
cc main.c -o app
# link libfoo dynamically
cc main.c -lfoo -o app
# static (if static libs available)
cc -static main.c -o app
Building a shared library (Linux)
cc -fPIC -c lib.c -o lib.o
cc -shared lib.o -o libfoo.so
cc main.c -L. -lfoo -o app
-fPIC generates position-independent code, required for shared libraries on most platforms.
How It Works
Static linking resolves all symbols at link time and copies code. Dynamic linking leaves some symbols unresolved; the dynamic loader resolves them at load (or lazily at first call) using the library's symbol table and relocations. Position-independent code (PIC) and the GOT/PLT (c.link.2) enable a shared library to be loaded at any address.
Variations
Static libraries (.a)
A static library is an archive of object files. The linker extracts only the members it needs. Created with ar.
Shared libraries (.so / .dylib / .dll)
Shared libraries have a different format per platform (ELF .so, Mach-O .dylib, PE .dll).
Lazy binding
By default, many functions in shared libraries are resolved lazily on first call via the PLT, improving startup time.
Common Mistakes
- Forgetting
-fPICwhen building a shared library. - Confusing the order of
-lflags (link order matters for static libs). - Assuming a statically linked binary is always portable (it is
self-contained but not necessarily ABI-portable across OS/arch).
Undefined Behavior
- None inherent to linking; a mismatched ABI or corrupt library can cause
crashes, but that is not ISO C UB.
Portability
- Static/dynamic linking concepts are universal; the flags and file extensions
are platform-specific.
Under the Hood
The dynamic loader (ld.so on Linux) reads the executable's dynamic section, loads required libraries, applies relocations, and transfers control. The GOT holds addresses of global data; the PLT provides lazy function resolution. c.link.2/c.link.3 cover this.
Practical Usage
- Prefer dynamic linking for general applications (updates, smaller size,
shared memory).
- Use static linking for self-contained deployment or minimal containers.
- Use
-fPICfor shared libraries and understand-shared.
Exercises
1. Build a small library both statically (.a) and dynamically (.so), and link a program against each. 2. Use ldd (Linux) or otool -L (macOS) to inspect dynamic dependencies. 3. Compare the size of a statically and dynamically linked binary.
Deep Challenge
Explain what happens at run time when a program calls a function in a shared library, from the PLT stub through the dynamic loader to the final call. Why does PIC and the GOT make this possible?
Related Concepts
c.build.2— symbols/relocations.c.link.2— GOT, PLT, PIC, PIE.c.sec.5— ASLR.
References
- GNU ld documentation; ELF specification; platform linker docs.
Verification
- Static vs. dynamic linking semantics.
VERIFIED -fPIC/-sharedfor shared libraries.VERIFIED- No example was executed during generation unless noted. `Execution not
verified.`
Progress
- [ ] Read
- [ ] Understand
- [ ] Complete examples
- [ ] Complete exercises
- [ ] Complete deep challenge
Concept checkboxes
- [ ] Static linking
- [ ] Dynamic linking
- [ ] Shared libraries
- [ ] PIC
- [ ] Static libraries (.a)
Mastery levels
| Concept | Current level (0–8) | Target level |
|---|---|---|
| c.build.static-link | 0 | 6 |
| c.build.dynamic-link | 0 | 6 |