Language 2 of 10 · Topic 0.10

Error & Exception Handling: try-catch, std::exception, noexcept & RAII Stack Unwinding

1Concept

C++ exception handling uses try, catch, and throw. When an exception is thrown, the runtime performs Stack Unwinding: all local stack variables in active frames are destroyed in reverse order, ensuring RAII destructors release resources. noexcept marks functions that guarantee never to throw, enabling compiler optimizations.

2Architecture Diagram

[try Block] ──► throw std::runtime_error("...")
      │
      ▼ [Stack Unwinding Initiated]
[Destroy Local Frame 2 (Call RAII Destructors)]
[Destroy Local Frame 1 (Call RAII Destructors)]
      │
      ▼
[catch (const std::exception& e)] ──► Handle error cleanly & Log e.what()

3Code Example

Stage 0 Language Foundations
#include <iostream>
#include <stdexcept>
#include <string>

class DatabaseConnection {
public:
    DatabaseConnection() { std::cout << "  -> DB Connection opened.\n"; }
    ~DatabaseConnection() { std::cout << "  -> DB Connection closed via RAII cleanup.\n"; }
};

void execute_query(int query_id) {
    DatabaseConnection conn; // Stack-allocated RAII object

    if (query_id < 0) {
        throw std::invalid_argument("Query ID cannot be negative!");
    }
    std::cout << "  -> Query " << query_id << " executed successfully.\n";
}

int main() {
    std::cout << "=== C++ Exception Handling & Stack Unwinding ===\n";

    try {
        std::cout << "Testing valid query:\n";
        execute_query(101);

        std::cout << "\nTesting invalid query (will throw):\n";
        execute_query(-5);
    } 
    catch (const std::invalid_argument& ex) {
        std::cerr << "[Caught Exception] " << ex.what() << "\n";
    }
    catch (const std::exception& ex) {
        std::cerr << "[General Exception] " << ex.what() << "\n";
    }

    std::cout << "Program recovered and continuing normally.\n";
    return 0;
}

4Expected Output

=== C++ Exception Handling & Stack Unwinding ===
Testing valid query:
  -> DB Connection opened.
  -> Query 101 executed successfully.
  -> DB Connection closed via RAII cleanup.

Testing invalid query (will throw):
  -> DB Connection opened.
  -> DB Connection closed via RAII cleanup.
[Caught Exception] Query ID cannot be negative!
Program recovered and continuing normally.

5Key Takeaways

  • Always catch exceptions by const reference (const std::exception& e) to avoid object slicing.
  • RAII destructors execute automatically during stack unwinding even when exceptions throw.
  • Mark move constructors and destructors noexcept for optimal vector resizing performance.