error_handling
Runtime Exceptions
Conditions that are possible and can happen during runtime, and can be handled without crashing. They are recoverable.
Programming Errors
Things that should never happen, like an array out of bounds. They represent programming or logical errors. They are unrecoverable.
Most common are invariant violations:
Array index out of bounds
Null pointer dereference
Division by zero
Impossible state combinations (e.g., a mutex both locked and unlocked)
Violation of logical constraints (e.g., a negative count of items)
How to Handle Each Type of Error
Use exceptions when:
Recovery is possible: The error condition might be handled and the program can continue execution
Expected failure conditions: For situations like file not found or network timeouts
Creating reusable libraries: Allows client code to handle errors in context-appropriate ways
Propagating errors up the call stack: When the handling code is far from where the error occurs
Constructor failures: Exceptions are the only clean way to handle initialization failures
Use LOG(FATAL) or CHECK when:
Programming errors: Assertions, invariant violations, and "this should never happen" scenarios
Unrecoverable states: When continuing execution would be unsafe or impossible
Performance-critical code: Where exception handling overhead is unacceptable
Core system functionality: Where simplicity and predictability are paramount
Clear contract violations: Such as null pointers or invalid arguments that indicate bugs
Invariant violations are typically handled with mechanisms like CHECK()
, assert()
, or LOG(FATAL)
since they represent programming errors that should be fixed rather than handled at runtime.
Exceptions are for exceptional but recoverable conditions
LOG(FATAL)/CHECK are for programming errors and invariant violations
In high-reliability systems, fatal crashes with clear error messages are often preferable to unpredictable behavior.
Fatal crashes are better for real-time code because:
Exception handling adds overhead
Exception handling is unpredictable; you don't want program flow to be very different based on exceptional circumstances. If something is very different, you prefer to crash.
Last updated