static vs dynamic linking
Imagine packing for a trip. You can stuff every tool you might need into your own suitcase so you are completely self-contained but heavy (static), or you can travel light and borrow the hotel's tools when you arrive, sharing them with other guests (dynamic). Static versus dynamic linking is this same choice for the library code a program depends on: bake your own copy into the executable, or fetch a shared copy at launch.
Static linking copies the needed library routines into the executable itself at build time. The result is one big, self-sufficient file that needs nothing else to run; every program that uses, say, a string library carries its own private copy. Dynamic linking instead leaves only a small stub in the executable; the actual library (a shared library: a .so file on Linux, a .dll on Windows) is loaded into memory at launch time and connected then, by the loader and a dynamic linker. Many programs can share one in-memory copy of the same library. This relies on position-independent code — code written so it works correctly no matter what address it is loaded at, so a single copy can serve everyone.
Why it matters: the trade-offs are real and opposite. Static linking gives a self-contained, fast-to-start, predictable program, but it is larger, wastes memory (each program duplicates the library), and to fix a library bug you must rebuild every program. Dynamic linking gives smaller executables, lets many programs share one copy in memory, and lets you patch a library once for everyone — but the program now depends on the right library version being present at run time, leading to the dreaded 'missing .dll / .so not found' failure and version-mismatch problems.
Twenty programs each use a 2 MB math library. Statically linked, that is twenty 2 MB copies on disk and in memory (40 MB). Dynamically linked, there is one 2 MB shared copy in memory that all twenty programs use.
Static = self-contained but duplicated; dynamic = shared but dependent on the library being present.
Dynamic linking's convenience has a cost: a program can break if the expected shared library is missing or the wrong version (DLL hell). Static linking avoids that fragility but cannot share a single in-memory copy across programs.