C++ 中的错误处理与异常:详细指南
What is it and why? (a real-life analogy)
Imagine you are a head chef in a large kitchen. You are preparing a complex dish according to a recipe. Everything is going well until suddenly... you run out of flour. Or the mixer breaks. Or someone accidentally switches the oven to a different mode.
What does an experienced chef do? He doesn't abandon everything and start shouting. He has a Plan B:
- If there is no flour — he uses a different kind.
- If the mixer breaks — he stirs by hand.
- If the oven settings are off — he adjusts the time.
The same thing happens in programming. Your code is the recipe. The computer is the kitchen. But the computer is not a perfect chef. It can:
- Fail to find the file you ask it to open.
- Attempt to divide a number by zero.
- Run out of memory.
- Receive "five" from the user instead of a number.
If you don't prepare for such situations, the program will simply crash (exit with an error). The user will see a scary window with incomprehensible text and will most likely close your program forever.
Error and exception handling is your "Plan B". It's a way to tell the program: "If something goes wrong — don't panic, do this instead, and then continue working".
Important: Error handling is not about hiding the problem. It's about keeping the program under control even in unforeseen situations.
Theory: how it works internally
Let's look "under the hood" and understand what happens in the computer when an error occurs.
Call Stack
When a program runs, the computer remembers which functions were called in the form of a stack — the call stack. Imagine a stack of plates:
- First, you call the function
main()— this is the first plate. - From
main(), you callcookPasta()— you put a second plate on top. - From
cookPasta(), you callboilWater()— the third plate.
If something goes wrong in boilWater(), the computer starts "removing plates" (terminating functions) one by one until it reaches main(). If there is no handler there either, the program crashes.
Exception Mechanism
An exception is a special object that is "thrown" at the location where the error occurred. This object travels up the call stack until it finds a suitable "catcher" (catch).
The process looks like this:
- Try: You mark a block of code where an error might occur.
- Throw: If the error happens, you create an exception object and "throw" it.
- Catch: You specify what type of exception to catch and what to do with it.
Important: If an exception is not caught anywhere, the program calls a special function std::terminate(), which terminates the program abnormally. This is exactly what we want to avoid.
Exception Types
In C++, you can throw anything: numbers, strings, objects. But professionals use special exception classes. The C++ standard library provides a hierarchy of classes:
| Class | What it means | Example |
|---|---|---|
std::exception |
Base class for all exceptions | Parent of all others |
std::runtime_error |
Error that can only be detected during program execution | File not found |
std::logic_error |
Error in program logic | Invalid function argument |
std::out_of_range |
Out of bounds access for an array or string | Accessing the 10th element of a 5-element array |
std::bad_alloc |
Failed to allocate memory | Array too large |
Syntax in C++: all forms and variants
In C++, there are three keywords for working with exceptions: try, throw, and catch. Let's break down each one.
Basic Construct
#include <iostream>
#include <stdexcept> // For standard exceptions
int main() {
try {
// Here we write code that might cause an error
int age;
std::cout << "Enter age: ";
std::cin >> age;
if (age < 0) {
// If age is negative — throw an exception
throw std::invalid_argument("Age cannot be negative!");
}
std::cout << "Your age: " << age << std::endl;
}
catch (const std::invalid_argument& e) {
// Catch exception of type invalid_argument
std::cout << "Error: " << e.what() << std::endl;
}
catch (const std::exception& e) {
// Catch ANY other standard exception
std::cout << "Unknown error: " << e.what() << std::endl;
}
// The program continues working!
std::cout << "Program completed successfully." << std::endl;
return 0;
}
Different ways of throwing
// Method 1: Throw a string
throw "This is an error string";
// Method 2: Throw a number
throw 42;
// Method 3: Throw a standard exception
throw std::runtime_error("Something went wrong");
// Method 4: Throw with