Shared Libraries
Shared libraries allow multiple programs to use the same compiled library code stored only once in memory and on disk. This reduces executable size, saves RAM, simplifies software updates, and enables runtime loading of functionality.
Learning Objectives
- Understand shared libraries.
- Compare static and shared libraries.
- Learn dynamic linking.
- Understand the dynamic loader.
- Learn library search paths.
- Prepare for runtime loading APIs.
1. What is a Library?
A library is a collection of reusable compiled functions and data that can be linked with one or more programs. Libraries reduce code duplication and promote software reuse.
2. Types of Libraries
| Type | Description |
|---|---|
| Static Library | Copied into the executable during linking. |
| Shared Library | Loaded dynamically at program startup or runtime. |
3. Static Linking
During static linking, the linker copies the required library code directly into the executable. Each executable contains its own copy of the library functions.
4. Shared Library
A shared library is stored separately from the executable. The executable contains references to the shared library, which is loaded into memory by the operating system when required.
5. Static vs Shared Libraries
| Feature | Static | Shared |
|---|---|---|
| Executable Size | Larger | Smaller |
| Memory Usage | Higher | Lower |
| Runtime Dependency | No | Yes |
| Library Updates | Requires rebuilding | Usually not required |
| Startup Time | Usually Faster | May require loading |
6. Dynamic Linking
Dynamic linking resolves library references when a program starts or when a library is loaded during execution. Only the required shared library is mapped into memory.
7. Dynamic Loader
The dynamic loader is responsible for locating required shared
libraries, loading them into memory, resolving external symbols,
and transferring control to the application.
On Linux, this loader is commonly implemented as
ld.so or ld-linux.so, depending on the
system architecture.
8. ELF Overview
Most modern UNIX and Linux systems use the Executable and Linkable Format (ELF) for executables, object files, and shared libraries. ELF stores metadata describing program sections, symbols, relocation information, and library dependencies.
9. Library Search Path
When a program starts, the dynamic loader searches for required shared libraries using configured search paths. Typical search locations include:
/lib/usr/lib/usr/local/lib- Directories configured by the system.
- Directories specified through environment variables (platform dependent).
10. Interview Questions
- What is a shared library?
- How does a shared library differ from a static library?
- What is dynamic linking?
- What is the purpose of the dynamic loader?
- What is ELF?
- Why are shared libraries memory efficient?
- Which file extension is commonly used for shared libraries?
- Why are static executables generally larger?
- Where does the loader search for shared libraries?
- Why are shared libraries widely used in modern operating systems?
11. Runtime Dynamic Loading
Unlike normal dynamic linking, runtime dynamic loading allows an application to load a shared library whenever it is needed. This enables plug-in architectures and optional functionality without requiring the library to be loaded when the application starts.
12. dlopen()
The dlopen() function loads a shared library into the
current process and returns a handle used for future operations.
13. Common dlopen() Flags
| Flag | Description |
|---|---|
RTLD_LAZY |
Resolve symbols only when first used. |
RTLD_NOW |
Resolve all symbols immediately. |
RTLD_GLOBAL |
Export loaded symbols for future libraries. |
RTLD_LOCAL |
Keep symbols local to the loaded library. |
14. dlsym()
The dlsym() function searches a loaded shared library
for a symbol such as a function or global variable.
15. dlclose()
The dlclose() function decreases the reference count of
a dynamically loaded library.
When the reference count reaches zero, the implementation may unload
the library.
16. dlerror()
The dlerror() function returns a human-readable string
describing the most recent dynamic loading error.
17. Runtime Symbol Resolution
18. Example Using dlopen()
19. Example Using dlsym()
20. Interview Questions
- What is the purpose of
dlopen()? - What does
dlsym()return? - Why is a function pointer required with
dlsym()? - What is the purpose of
dlerror()? - What happens when
dlclose()is called? - What is the difference between
RTLD_NOWandRTLD_LAZY? - What is runtime symbol resolution?
- Which header declares the runtime loading functions?
- How are plug-in architectures implemented using shared libraries?
- Why should every call to
dlopen()eventually be matched bydlclose()?
21. Building a Shared Library
A shared library is typically compiled as Position Independent Code (PIC) and then linked into a shared object file.
22. Position Independent Code (PIC)
Position Independent Code (PIC) allows executable instructions to run correctly regardless of the memory address where the library is loaded. This enables the operating system to load the same shared library into different virtual addresses for different processes.
23. Creating a Static Library
Static libraries are archive files that contain one or more object
modules.
The ar utility is commonly used to create archive files.
24. Linking with Libraries
Applications can link against libraries using the
-L and -l compiler options.
Where:
| Option | Description |
|---|---|
-L |
Specifies a library search directory. |
-l |
Specifies the library name without the lib prefix or extension. |
25. Runtime Library Search
26. Linux Library Commands
| Command | Purpose |
|---|---|
ldd app |
Display shared library dependencies. |
ldconfig |
Update shared library cache. |
nm libmath.so |
Display exported symbols. |
objdump -T libmath.so |
Display dynamic symbol table. |
readelf -d libmath.so |
Display dynamic section. |
27. Library Development Workflow
28. Best Practices
- Compile shared libraries using
-fPIC. - Export only the symbols required by users of the library.
- Maintain backward compatibility whenever possible.
- Always verify the return value of
dlopen(). - Release dynamically loaded libraries using
dlclose(). - Document exported APIs clearly.
29. Common Programming Mistakes
- Building shared libraries without
-fPIC. - Forgetting to link with the required library.
- Ignoring errors returned by
dlopen(). - Using incorrect library search paths.
- Calling
dlsym()with an invalid symbol name. - Forgetting to call
dlclose().
30. Interview Questions
- Why is
-fPICrequired for shared libraries? - What is Position Independent Code?
- How is a static library created?
- What is the purpose of the
arutility? - What does the
-Lcompiler option do? - Why is the
-loption used without thelibprefix? - Which Linux command displays shared library dependencies?
- What information does
nmdisplay? - What is the purpose of
ldconfig? - Why should only necessary symbols be exported from a shared library?
31. Runtime Loading API Comparison
| Function | Purpose |
|---|---|
dlopen() |
Load a shared library. |
dlsym() |
Locate a symbol within a loaded library. |
dlerror() |
Retrieve the last dynamic loading error. |
dlclose() |
Release a dynamically loaded library. |
32. Static vs Dynamic Linking Comparison
| Feature | Static Linking | Dynamic Linking |
|---|---|---|
| Executable Size | Larger | Smaller |
| Memory Usage | Separate copy per executable | Shared among processes |
| Program Startup | No runtime library loading | Dynamic loader resolves libraries |
| Library Updates | Application must be rebuilt | Usually only library replacement is required* |
| Runtime Loading | Not supported | Supported through dlopen() |
*Provided the updated library remains binary compatible with the application.
33. Complete Shared Library Workflow
34. Linux Commands Summary
| Command | Purpose |
|---|---|
ldd |
Show shared library dependencies. |
ldconfig |
Update and display shared library cache. |
nm |
Display symbol table information. |
objdump -T |
Display exported dynamic symbols. |
readelf -d |
Display ELF dynamic section. |
file |
Identify executable and library file types. |
35. Best Practices Review
- Compile shared libraries using
-fPIC. - Check the return value of
dlopen()before using the library handle. - Use
dlerror()immediately after runtime loading failures. - Export only stable public APIs.
- Maintain binary compatibility across library versions whenever possible.
- Release library handles with
dlclose().
36. Common Programming Mistakes
- Forgetting to compile shared libraries using
-fPIC. - Ignoring errors returned by
dlopen(). - Casting function pointers incorrectly after
dlsym(). - Assuming every library update is binary compatible.
- Using incorrect runtime library search paths.
- Forgetting to release dynamically loaded libraries.
37. Advanced Interview Questions
- Why are shared libraries preferred over static libraries in modern operating systems?
- Explain Position Independent Code (PIC).
- How does
dlopen()differ from normal dynamic linking? - Why is
dlsym()required after callingdlopen()? - What is binary compatibility?
- Why should shared libraries expose only required symbols?
- How does the dynamic loader resolve external symbols?
- Which command displays the dynamic dependencies of an executable?
- Why is
dlerror()important for debugging? - How are plug-in architectures implemented using shared libraries?
38. Module Summary
This module introduced shared libraries and dynamic linking in UNIX
systems.
We studied static and shared libraries, Position Independent Code,
dynamic loading using dlopen(),
dlsym(), dlerror(), and
dlclose(), library creation, runtime linking,
library inspection tools, development workflow, best practices,
and common programming mistakes.
Shared libraries are fundamental to modern UNIX software because they
reduce executable size, improve memory utilization, simplify software
maintenance, and enable modular application design through runtime
loading.
Concept Mastery Assessment — Module 38
Verify your conceptual understanding with 12 targeted technical assessment questions. Instant feedback and explanations are provided for every choice.