C++
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C++
-
Section 4: Memory Management
-
Section 5: Templates and Generic Programming
-
Section 6: The Standard Template Library
-
Section 7: Modern C++ Features
-
Section 8: Error Handling
-
Section 9: Multithreading
-
Section 10: Operator Overloading and Type Conversion
-
Section 11: Advanced Topics
-
Section 12: Tooling and Build Systems
-
Section 13: Design Patterns in C++
-
Section 14: Interfacing with C and Systems Programming
-
Section 15: Networking and IPC Basics
-
Section 16: Graphics and Game Programming Basics
-
Section 17: The Boost Libraries
-
Section 18: Data Structures and Algorithms in C++
-
Section 19: Practical Projects
-
Section 20: More Concurrency Patterns
-
Section 21: More OOP and Design Practice
-
Section 22: File I/O and Streams
-
Section 23: More Standard Library
-
Section 24: Practice Exercises
-
Section 25: Interview and Algorithm Practice
-
Section 26: Compiler and Language Internals
-
Section 27: GUI and Application Frameworks Overview
-
Section 28: Testing and Quality Practices
-
Section 29: Numerics Library
-
Section 30: Concepts Library (C++20)
-
Section 31: Ranges Library (C++20) In Depth
-
Section 32: More Utility Library
128: Static vs Dynamic Libraries
You've probably heard the common wisdom that dynamic libraries are "better" because they save memory. The logic usually goes like this: "If ten different programs all use the same library, why put a copy of that code in ten different executables? Just put it in one .so or .dll and let them all share it."
On paper, that sounds like a win. In practice, it's a massive oversimplification that often leads developers to choose dynamic linking for the wrong reasons. If you're building a standalone tool, dynamic linking doesn't "save" you anything—it actually adds a layer of indirection that can slow down your function calls and, more annoyingly, creates a deployment nightmare where your app crashes because the user has the "wrong version" of a library installed. I've spent more hours than I care to admit debugging "DLL Hell" on client machines just because someone thought dynamic linking was the "efficient" choice.
The "Shared Memory" Magic Trick vs. Runtime Overhead
Let's look at a real example. Imagine you're writing a high-frequency trading application that uses a specialized library for Fast Fourier Transforms (FFT). If you link that FFT library statically, the linker takes the exact machine code for the functions you actually used and bakes them directly into your binary. When your code calls compute_fft(), the CPU jumps straight to a known memory address. It's fast, it's direct, and it's atomic.
Now, if you link it dynamically, your executable doesn't actually contain the FFT code. Instead, it contains a "stub" or a reference. When you launch the program, the OS loader has to find the .so or .dll on the disk, load it into memory, and resolve the addresses of the functions you need. This happens via a lookup table (called the PLT or Global Offset Table in Linux). Every single call to compute_fft() now requires an extra jump through this table. For most apps, this is negligible. For a low-latency trading app? It's a performance tax you don't want to pay.
// This looks the same in your code regardless of linking...
#include "fft_library.h"
int main() {
double data[1024];
// ... fill data ...
compute_fft(data); // Static: Direct jump. Dynamic: Lookup table jump.
return 0;
}
The "Binary Bloat" Myth vs. Linker Optimization
The other big misconception is that static libraries make your binaries "bloated." People assume that if a static library is 10MB, your executable grows by 10MB. This is fundamentally wrong because of how the linker works.
When you link dynamically, you are forced to load the entire library into memory, even if you only use one single function from it. The OS can't selectively load half of a .dll. However, when you link statically, the linker performs something akin to "tree shaking." It looks at your code, sees that you only called compute_fft() and ignored the other 500 functions in the library, and it only pulls the necessary object files into your final executable.
I've seen cases where a statically linked binary is actually smaller than the combined size of a dynamically linked binary and its required dependencies. So, if your goal is a portable, "single-file" distribution that doesn't break when the user updates their system libraries, static is your best friend.
- Use Static (.a / .lib) when you want maximum performance, easier deployment, and you don't mind slightly longer link times during development.
- Use Dynamic (.so / .dll) when you are building a plugin system, when the library is truly massive and used by dozens of different processes simultaneously, or when you need to be able to update the library without recompiling the main application.
📋 Practical Task
Building a Shared Math-Utility Library for a Multi-Binary Project
To truly understand the difference, you need to see the linker in action. Your task is to create a project consisting of one shared library and two separate executables that depend on it. This will simulate a real-world scenario where multiple tools share a common engine.
Requirements:
- Create a library called
libMathUtils. It should contain at least two functions:calculate_sphere_volume(double radius)andcalculate_cylinder_volume(double radius, double height). - Create two separate C++ programs:
SphereTool: Only uses the sphere volume function.CylinderTool: Only uses the cylinder volume function.
- Compile
libMathUtilsas a dynamic/shared library (use-shared -fPICif you are on Linux/macOS). - Link both
SphereToolandCylinderToolagainst this shared library. - The Test: Run the programs. Then, try to move the
.soor.dllfile to a different folder and run the programs again. Observe the error message from the OS loader. This is the "Dynamic Linking" fragility we discussed.
Bonus Challenge: Re-compile the entire project using static linking (creating a .a or .lib file). Verify that the executables now run perfectly even after you delete the library file from the disk.
There are no comments for now.