What is the primary advantage of table-driven exception handling over the setjmp/longjmp approach?
ATable-driven handling is simpler for the compiler to implement correctly
BTable-driven handling adds no overhead to code that does not throw — the exception table is only consulted when an exception actually occurs
CTable-driven handling allows exceptions to be caught across multiple stack frames simultaneously
DTable-driven handling eliminates the need to run destructors and finally blocks during unwinding
This is the key design tradeoff. With setjmp/longjmp, every entry into a try block executes setjmp to save state, incurring runtime cost on the common (non-exceptional) path. Table-driven handling shifts all that overhead to a static table stored alongside the compiled code. When no exception occurs — which is the normal case — the table is never accessed and execution runs at full speed. The cost is paid only when an exception actually occurs, making it 'zero-cost' for the common path.
Question 2 Multiple Choice
During stack unwinding after an exception is thrown, what happens when the runtime examines a stack frame that does not contain a matching catch handler?
AExecution returns immediately to the frame's caller without running any cleanup
BThe runtime runs any registered cleanup code (destructors, finally blocks) for that frame, then continues unwinding to the caller
CThe runtime terminates the program immediately since no matching handler was found
DThe runtime suspends unwinding and searches through all loaded libraries for a matching handler
Stack unwinding is not simply jumping to a handler — it must ensure that every stack frame's cleanup code runs in order. When no catch handler matches in a frame, the runtime still consults the exception table to find registered cleanup code (C++ destructors, Java/Python finally blocks) and executes it before discarding the frame and moving to the caller. This is what ensures resource cleanup (closing files, releasing locks) happens correctly even during exceptional control flow.
Question 3 True / False
Table-driven exception handling executes additional instructions on most function entry and return to prepare for potential exceptions.
TTrue
FFalse
Answer: False
This describes setjmp/longjmp-based exception handling, not table-driven. Table-driven (zero-cost) exception handling stores exception metadata in a separate section of the binary (e.g., DWARF .eh_frame on Unix). The normal code path executes identically to code with no exception handling at all — there are no extra instructions at function entry or return. The metadata is accessed only by the runtime unwinder, and only when an exception is actually thrown.
Question 4 True / False
The compiler must emit exception tables that account for every possible throw point within a function, not just the explicit throw statements.
TTrue
FFalse
Answer: True
Exceptions can originate from many implicit sources — calling a function that throws, constructing an object whose constructor throws, allocating memory that throws std::bad_alloc. The exception table must map every program counter range where an exception could propagate (not just explicit throw sites) to the appropriate cleanup and handler information. Missing a throw point could leave resources unreleased or skip a required finally block, causing correctness bugs that are difficult to diagnose.
Question 5 Short Answer
Explain why table-driven exception handling is called 'zero-cost' and what tradeoff this design involves compared to setjmp/longjmp.
Think about your answer, then reveal below.
Model answer: Table-driven handling is 'zero-cost' because it adds no runtime overhead to the normal (non-exceptional) execution path. Instead of executing instructions at try block entry, the compiler generates a static exception table stored alongside the code. This table maps program counter ranges to handler and cleanup information, but it is never consulted during normal execution. The tradeoff is that when an exception does occur, handling it is more expensive than with setjmp/longjmp — the runtime must walk the table and unwind through frames rather than simply restoring a saved context. For languages where exceptions are rare and try blocks are common, paying extra on the rare exceptional path is far better than paying a small cost on every try block entry.
The design choice reflects the principle of optimizing for the common case. In most programs, exceptions genuinely are exceptional — they occur infrequently relative to normal function calls. Paying a cost on every try block entry (setjmp) to save microseconds on the rare throw is the wrong optimization. Table-driven handling inverts this: zero cost on the common path, higher cost on the rare exceptional path.