C++ - Error Handling & Exceptions

Overview

Estimated time: 45–65 minutes

Use exceptions for error reporting in exceptional, non-local situations. Learn try/catch, standard exceptions, noexcept, and exception-safety with RAII.

Learning Objectives

  • Throw and catch exceptions; use standard exception types.
  • Understand noexcept and when to use it.
  • Design code with RAII so resources are released on exception paths.

Prerequisites

Throw and catch

#include <stdexcept>
#include <iostream>
int parse_positive(int x){ if (x <= 0) throw std::invalid_argument("non-positive"); return x; }
int main(){
  try {
    std::cout << parse_positive(1) << "\n";
    std::cout << parse_positive(0) << "\n"; // throws
  } catch (const std::invalid_argument& e) {
    std::cout << "error: " << e.what() << "\n";
  }
}

Expected Output: 1 error: non-positive

noexcept and strong exception safety

#include <vector>
#include <iostream>
void may_throw(){ throw 42; }
void safe() noexcept { /* won't throw */ }
int main(){
  try { may_throw(); } catch(...) { std::cout << "caught\n"; }
  safe();
}

RAII to the rescue

#include <fstream>
#include <string>
#include <iostream>
void write_line(const std::string& path){
  std::ofstream out(path); // closed automatically even if exceptions occur later
  if (!out) throw std::runtime_error("open failed");
  out << "line\n";
}

Beginner Boosters

#include <stdexcept>
#include <string>
#include <iostream>
int to_int(const std::string& s){
  for (char c: s) if (c < '0' || c > '9') throw std::invalid_argument("not a digit");
  return std::stoi(s);
}
int main(){
  try { std::cout << to_int("123") << "\n"; std::cout << to_int("1x") << "\n"; }
  catch(const std::exception& e){ std::cout << e.what() << "\n"; }
}

Common Pitfalls

  • Using exceptions for normal control flow; prefer return status for expected outcomes.
  • Catching by value (slicing); catch exceptions by const reference.
  • Forgetting RAII; leaking resources on throw paths.

Checks for Understanding

  1. When should you use exceptions vs return codes?
  2. Why catch exceptions by const reference?
Show answers
  1. Exceptions for exceptional, non-local errors; return codes for expected results.
  2. To avoid slicing and unnecessary copies; preserve dynamic type.

Exercises

  1. Write a function that opens a file and throws std::runtime_error on failure; write tests using try/catch.
  2. Mark a function noexcept and verify the compiler enforces it by preventing throws.