Computer Science › Compilers & Languages
Static vs Dynamic Linking
Bundling libraries into the binary vs loading them at runtime.
Also known as: static vs dynamic linking, static linking, dynamic linking
When your program uses a library, the linker can either fold it into the executable or leave a reference to load later. That’s the choice between static and dynamic linking.
- Static linking copies the library’s code into your binary at build time. The result is self-contained: it carries everything it needs.
- Dynamic linking leaves a reference, and at startup a loader finds the shared library (
.soon Linux,.dylibon macOS,.dllon Windows) and connects it.
static: program + libfoo (all inside) → one big, self-contained file
dynamic: program ──references──▶ libfoo.so → smaller, but needs libfoo present
The trade-offs cut both ways:
- Static — simpler to ship (no missing-library surprises), no runtime lookup cost, but larger binaries and, crucially, a security patch to a library means rebuilding every program that used it.
- Dynamic — smaller binaries, libraries shared in memory across programs, and a patched library fixes everything at once — but the target must have a compatible version, and mismatches cause “not found” or symbol errors.
This is why container images care: a static binary (scratch base) has no library dependencies; a dynamically linked one needs its libraries present in the image. It’s also why system updates can fix a library vulnerability everywhere by replacing one .so.
The classic mistakes:
- Assuming “compiled” means one file. A dynamically linked binary needs its libraries at runtime; copy it alone and it may fail to start.
- Version skew on the target. Linking against a newer library than the target has causes load failures. Match the build to the deployment environment (see cross-compilation).
- Forgetting to relink after a static-library patch. With static linking, the fix isn’t automatic; you must rebuild and redeploy the program.
- Ignoring the “DLL hell” / dependency hell risk. Shared libraries with incompatible versions side by side are a classic source of breakage.
- Choosing by reflex. Static suits self-contained tools and containers; dynamic suits shared system libraries. Pick deliberately.
The choice is a real engineering trade: portability and safety-patch reach versus simplicity and binary size. It shows up most in how you build and ship binaries — and it’s a frequent reason containers fail with a missing .so that the build machine had.