In C++, handling unexpected runtime errors can be accomplished using exceptions. While exceptions provide a clean separation between business logic and error handling, they carry major compiler costs that every systems developer must understand.
Let's look at try catch blocks, binary table overheads, and stack frame unwinding.
How Exceptions Work: The Happy Path vs The Sad Path
C++ exceptions use a model known as the Zero Cost Exception Model. This name is slightly misleading. It means that as long as no exception is thrown (the happy path), execution experiences zero runtime overhead. There are no active branch checks or registers allocated to exception tracking.
However, when an exception is thrown (the sad path), execution speeds drop significantly. The operating system must perform stack frame unwinding:
1. The runtime stops normal code execution.
2. It scans compiler generated lookup tables (exception tables) to locate a catch block matching the thrown type.
3. It steps backward through active stack frames, calling destructors for all local variables in those frames to prevent memory leaks.
4. It restores CPU registers to the state of the catch block and resumes execution.
This unwinding process can take thousands of CPU cycles, making exceptions extremely slow for regular flow control.
Binary Size Overhead
To enable stack unwinding, the compiler must generate extra metadata tables containing instruction offsets and destructor mappings. This metadata is stored in your final compiled binary, increasing the binary size by 10 to 30 percent, even if your code never throws an exception. This is why latency critical applications (such as game engines, database kernels, and embedded systems) compile code with exceptions completely disabled using flags like -fno-exceptions.
* The Emergency Train Brake Metaphor: Throwing an exception is like pulling the emergency brake on a high speed train. It stops the train and keeps everyone safe, but the sudden friction damages the wheels, and resetting the systems takes a long time. You would never pull the brake just to slow down for a station (standard code flow).