Exception Handling
Standard Exceptions
Explore the C++ standard library exception hierarchy, separating logic errors from runtime errors.
Interview: Differentiating between std::logic_error and std::runtime_error, and mapping common standard exceptions to their typical root causes.
C++ provides a structured Standard Exception Hierarchy defined in the <stdexcept> header. All standard exceptions derive from the base class std::exception, exposing the virtual member function what() to retrieve error details.
| Exception Type | Classification | Root Cause Examples |
|---|---|---|
| std::invalid_argument | Logic Error | Passing an invalid value to a function (e.g. negative index). |
| std::out_of_range | Logic Error | Accessing vector elements out of bounds (e.g., using vector::at). |
| std::overflow_error | Runtime Error | Arithmetic computation exceeding storage type limit. |
| std::bad_alloc | Resource Error | Memory allocation via new operator fails. |
Logic Error vs. Runtime Error
The standard library divides exceptions into two primary branches:
- std::logic_error: Represents bugs that can be avoided through static code checks and validation (e.g., out-of-range indices or invalid arguments).
- std::runtime_error: Represents errors that occur due to environmental factors outside the control of the program (e.g., file-system locks, network disconnects, or hardware overflows).
Code Walkthrough
Demonstrates throwing and catching standard logic and runtime exceptions.
#include <iostream> #include <vector> #include <stdexcept>void accessVector(const std::vector<int>& vec, size_t index) { if (index >= vec.size()) { throw std::out_of_range("Vector index out of range!"); } std::cout << "Value: " << vec.at(index) << std::endl; }
int main() { std::vector<int> numbers = {1, 2, 3}; try { accessVector(numbers, 5); } catch (const std::out_of_range& e) { std::cerr << "Logic error caught: " << e.what() << std::endl; } catch (const std::exception& e) { std::cerr << "Standard exception caught: " << e.what() << std::endl; } return 0; }
Interview-Relevant Information
Q: How do std::logic_error and std::runtime_error differ conceptually?
Answer: std::logic_error represents logical errors in program design (like passing invalid bounds) that could theoretically be prevented at compile time or through strict input validation. std::runtime_error represents unpredictable anomalies caused by the external environment (like database timeouts or missing configurations) that must be handled dynamically at runtime.
Q: What does std::bad_alloc indicate?
Answer: std::bad_alloc is thrown by the global operator new when it cannot allocate the requested amount of dynamic memory. Catching this exception allows programs to release cached resources or log emergency states before termination.
Quick Checklist
Do you know when to use invalid_argument vs runtime_error? Do you access elements with bounds checking? If yes, you understand standard exceptions.
Use Cases
Leveraging standard library boundary checking (like vector::at) to capture indexing errors.
Safely managing dynamic memory allocations and recovering from bad_alloc errors.
Common Mistakes
Throwing std::exception directly instead of a more specific standard class like invalid_argument or runtime_error.
Conflating std::logic_error and std::runtime_error, resulting in confusing classification for library users.