A desk builds its order gateway with -fno-exceptions and returns error codes instead. State the real cost model of a C++ exception, say why zero-cost is a misleading description for a latency sensitive path, and say what error codes cost in exchange.

A desk builds its order gateway with -fno-exceptions and returns error codes instead. State the real cost model of a C++ exception, say why zero-cost is a misleading description for a latency sensitive path, and say what error codes cost in exchange.

Approach: Separate the cost when nothing is thrown from the cost when something is, then ask what the unwinder must do and what the optimiser may not do around a call that can throw.

On the path where nothing throws, a table driven exception costs no extra instructions, and the throw path costs microseconds because the unwinder walks the stack frames and decodes compressed unwind tables from a cold section, often taking a process wide lock, so the objection is tail latency and its unpredictability. Zero cost describes the untaken path only, and even there the compiler must keep cleanup code reachable and may not move work across a call that can throw, which costs some optimisation and grows the binary, adding instruction cache pressure. Error codes cost one well predicted branch after every call, under a nanosecond, plus the risk that a returned code is ignored, which is why the discipline is a result type marked nodiscard. Exceptions are cheaper on average and much worse at the 99.99th percentile, and a gateway is judged on the tail.

Follow-up: With -fno-exceptions in force, what happens when a vector fails to allocate, and what happens inside a third party library you link that does throw?

Key concepts: zero-cost exceptions, stack unwinding, tail latency, error codes.