Dynamic Linking vs Static Linking
Dynamic linking vs static linking explained — build-time vs runtime resolution, trade-offs, and examples — OS interview questions answered.
Expected Interview Answer
Static linking copies all the library code a program needs directly into its final executable at build time, while dynamic linking leaves references to shared libraries unresolved until load time or runtime, letting multiple programs share a single copy of the library in memory.
With static linking, the linker resolves every external symbol and embeds the actual machine code of the required libraries into the output binary, producing a single self-contained executable that has no runtime dependency on those libraries being present elsewhere. With dynamic linking, the executable instead contains a table of unresolved references to shared library functions, and the OS’s dynamic loader maps the shared library into the process’s address space and patches those references when the program starts, or even lazily on first call. Static linking yields faster startup and no missing-dependency risk but larger binaries and duplicated code across every program that links the same library, while dynamic linking yields smaller binaries, shared physical memory pages across processes using the same library, and the ability to patch a library (like fixing a security bug) without recompiling every dependent program. The trade-off is that dynamic linking introduces "DLL hell" style version-mismatch risk and slightly slower startup due to the resolution step.
- Static linking: predictable, self-contained, no missing-dependency failures
- Dynamic linking: smaller binaries and shared physical memory across processes
- Dynamic linking: security patches apply without recompiling every program
- Understanding both explains executable size, startup time, and deployment trade-offs
AI Mentor Explanation
Static linking is like a coaching manual that copies every relevant fielding drill in full into each individual player’s personal handbook, so every player carries their own complete copy and needs nothing else on match day. Dynamic linking is like the team sharing one master drill board pinned in the pavilion that every player consults during the match, so updating a drill on the board instantly applies to everyone without reprinting handbooks. The shared board saves paper but means the pavilion board must actually be present and correct on match day.
Step-by-Step Explanation
Step 1
Compilation
Source code is compiled into object files containing unresolved external symbol references.
Step 2
Static linking path
The linker copies the actual library machine code into the final executable, resolving all symbols at build time.
Step 3
Dynamic linking path
The linker instead leaves a table of unresolved references and records which shared libraries are needed.
Step 4
Load-time resolution
For dynamic linking, the OS loader maps the shared library into the process’s address space and patches the references before or during execution.
What Interviewer Expects
- Clear distinction between build-time and load/run-time symbol resolution
- Trade-offs: binary size, startup time, memory sharing, patchability
- Awareness of the risk of missing or mismatched shared libraries
- Ability to give a concrete example (e.g., libc as a shared library)
Common Mistakes
- Thinking dynamic linking always makes programs run faster
- Not knowing shared libraries let multiple processes share physical memory pages
- Forgetting static linking avoids missing-dependency failures at deploy time
- Confusing dynamic linking with dynamic memory allocation
Best Answer (HR Friendly)
“Static linking bakes all the library code a program needs right into the final executable, so it runs standalone but is larger. Dynamic linking instead has the program pull in shared library code at startup, which keeps binaries smaller and lets many programs share one copy in memory, at the cost of needing that shared library to actually be present and compatible on the machine.”
Code Example
/* Static linking: library code copied into the final binary */
gcc main.c -static -lmylib -o app_static
/* Dynamic linking: binary references libmylib.so, resolved at load time */
gcc main.c -lmylib -o app_dynamic
/* At runtime, the loader must find libmylib.so, e.g. via LD_LIBRARY_PATH */
/* Runtime symbol lookup sketch performed by the dynamic loader */
void *handle = dlopen("libmylib.so", RTLD_LAZY);
void (*fn)(void) = dlsym(handle, "mylib_function");
fn();Follow-up Questions
- What is lazy binding in dynamic linking and how does it improve startup time?
- How do multiple processes share physical memory pages for the same shared library?
- What happens if a required shared library is missing or the wrong version at load time?
- What is position-independent code and why does dynamic linking need it?
MCQ Practice
1. When is a library’s code actually copied into the executable, in static linking?
Static linking resolves and embeds the library’s machine code into the final executable during the link step at build time.
2. What is a key advantage of dynamic linking over static linking?
Because the shared library is mapped once and shared across processes, dynamic linking saves physical memory and disk space compared to static linking.
3. A risk unique to dynamic linking is?
Because dynamic linking resolves references at load/runtime, a missing or mismatched shared library version can prevent the program from running — sometimes called "DLL hell."
Flash Cards
What is static linking? — Copying library machine code directly into the executable at build time.
What is dynamic linking? — Leaving library references unresolved until load/runtime, using a shared library file.
Key benefit of dynamic linking? — Shared physical memory pages across processes and patchable libraries without recompiling.
Key benefit of static linking? — Self-contained binary with no missing-dependency risk at deploy time.