Error Handling in C++: try/catch from A to Z – Complete Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Error Handling is the Foundation of Reliable C++ Code



Any program interacting with the outside world (files, network, user input) inevitably encounters exceptional situations. In C++, the try/catch mechanism is the primary tool for elegant and controlled management of such situations. In this article, we will break down error handling in C++ from basic constructs to advanced techniques, including best practices and pitfalls.



1. Basics: try, catch, and throw



The exception mechanism in C++ is built on three key keywords: try, catch, and throw.



1.1. The try and catch Block

A try block contains code that may throw an exception. A catch block catches this exception and handles it.



#include <iostream>#include <stdexcept>

int main() { try { // Code that may cause an error int age = -5; if (age < 0) { throw std::invalid_argument("Age cannot be negative"); } std::cout << "Age: " << age << std::endl; } catch (const std::invalid_argument& e) { std::cerr << "Error: " << e.what() << std::endl; } return 0;}


1.2. Exception Types

In C++, you can throw exceptions of any type: numbers, strings, class objects. However, it is recommended to use standard exception classes from <stdexcept> or create your own classes inherited from std::exception.



  • Standard exceptions: std::runtime_error, std::logic_error, std::out_of_range, etc.
  • Custom exceptions: created by inheriting from std::exception.


class MyException : public std::exception {public:    const char* what() const noexcept override {        return "My custom exception";    }};


1.3. Multiple catch Blocks

You can catch different types of exceptions in separate catch blocks. Order matters: more specific exceptions should come first.



try {    // code} catch (const std::invalid_argument& e) {    // handle invalid_argument} catch (const std::exception& e) {    // handle all other exceptions from std} catch (...) {    // catch-all: catches everything not caught above}


2. Advanced Techniques: Stack Unwinding and RAII



2.1. Stack Unwinding

When an exception is thrown, C++ automatically destroys all local objects on the path from the throw point to the corresponding catch. This process is called stack unwinding. It guarantees destructor calls for all objects created in try blocks.



class Resource {public:    Resource() { std::cout << "Resource created"; }    ~Resource() { std::cout << "Resource destroyed"; }};

void riskyFunction() { Resource res; throw std::runtime_error("Something went wrong");}

int main() { try { riskyFunction(); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } // Output: Resource created -> Resource destroyed -> Something went wrong}


2.2. RAII (Resource Acquisition Is Initialization)

RAII is a key C++ idiom closely tied to error handling. The idea: resource management (memory, files, mutexes) is tied to the lifetime of an object. The destructor automatically releases the resource, even during an exception.



  • Smart pointers: std::unique_ptr, std::shared_ptr

Blogs

Book Recommendations