Bỏ qua để đến nội dung

Xử lý ngoại lệ (Exception Handling)

Ngoại lệ (exception) là cơ chế để xử lý các tình huống lỗi xảy ra lúc chạy chương trình (runtime errors) một cách có kiểm soát, thay vì để chương trình crash đột ngột.

#include <iostream>
int main() {
try {
int a = 10;
int b = 0;
if (b == 0) {
throw std::runtime_error("Khong the chia cho 0");
}
std::cout << a / b << std::endl;
} catch (const std::runtime_error& e) {
std::cout << "Loi: " << e.what() << std::endl;
}
std::cout << "Chuong trinh tiep tuc chay binh thuong" << std::endl;
return 0;
}
  • try { ... }: khối code có khả năng gây ra lỗi
  • throw: “ném” ra một ngoại lệ khi phát hiện tình huống lỗi
  • catch (kiểu_exception& e) { ... }: “bắt” và xử lý ngoại lệ tương ứng

Thư viện chuẩn (<stdexcept>) cung cấp sẵn nhiều kiểu exception cho các tình huống phổ biến:

#include <stdexcept>
#include <iostream>
#include <vector>
int main() {
try {
std::vector<int> numbers = {1, 2, 3};
std::cout << numbers.at(10) << std::endl; // Ném std::out_of_range
} catch (const std::out_of_range& e) {
std::cout << "Loi pham vi: " << e.what() << std::endl;
}
try {
throw std::invalid_argument("Gia tri khong hop le");
} catch (const std::invalid_argument& e) {
std::cout << "Loi doi so: " << e.what() << std::endl;
}
return 0;
}
Kiểu exception Dùng khi nào
std::runtime_error Lỗi chung xảy ra lúc chạy chương trình
std::out_of_range Truy cập ngoài phạm vi hợp lệ (ví dụ vector::at)
std::invalid_argument Đối số truyền vào không hợp lệ
std::logic_error Lỗi logic trong chương trình (có thể phát hiện trước khi chạy)
#include <iostream>
#include <stdexcept>
void process(int value) {
if (value < 0) {
throw std::invalid_argument("Gia tri khong duoc am");
}
if (value > 100) {
throw std::out_of_range("Gia tri vuot qua 100");
}
std::cout << "Xu ly gia tri: " << value << std::endl;
}
int main() {
try {
process(-5);
} catch (const std::invalid_argument& e) {
std::cout << "Loi doi so: " << e.what() << std::endl;
} catch (const std::out_of_range& e) {
std::cout << "Loi pham vi: " << e.what() << std::endl;
} catch (const std::exception& e) { // Bắt mọi exception khác kế thừa từ std::exception
std::cout << "Loi khac: " << e.what() << std::endl;
}
return 0;
}
try {
// code có thể ném bất kỳ loại exception nào
} catch (...) {
std::cout << "Da xay ra loi khong xac dinh" << std::endl;
}

Nên hạn chế dùng catch (...) trừ khi thực sự cần thiết, vì nó “nuốt” mọi lỗi mà không cho biết chi tiết nguyên nhân.

Bạn có thể tạo kiểu exception riêng bằng cách kế thừa từ std::exception:

#include <exception>
#include <iostream>
class InsufficientBalanceException : public std::exception {
public:
const char* what() const noexcept override {
return "So du khong du de thuc hien giao dich";
}
};
void withdraw(double balance, double amount) {
if (amount > balance) {
throw InsufficientBalanceException();
}
std::cout << "Rut tien thanh cong: " << amount << std::endl;
}
int main() {
try {
withdraw(100, 200);
} catch (const InsufficientBalanceException& e) {
std::cout << "Loi: " << e.what() << std::endl;
}
return 0;
}

C++ không có khối finally như một số ngôn ngữ khác. Thay vào đó, nguyên lý RAII (đã đề cập ở bài Smart Pointers) đảm bảo tài nguyên luôn được giải phóng đúng cách khi một đối tượng ra khỏi phạm vi, dù có exception xảy ra hay không:

#include <memory>
#include <iostream>
void process() {
auto ptr = std::make_unique<int>(42); // RAII: tự động giải phóng dù có exception hay không
throw std::runtime_error("Loi xay ra!");
// Bộ nhớ vẫn được giải phóng đúng cách nhờ unique_ptr, dù dòng dưới không bao giờ chạy tới
}
int main() {
try {
process();
} catch (const std::exception& e) {
std::cout << "Da bat loi: " << e.what() << std::endl;
}
return 0;
}
  • try/catch/throw cho phép xử lý lỗi lúc chạy chương trình một cách có kiểm soát
  • Thư viện chuẩn cung cấp sẵn nhiều kiểu exception (runtime_error, out_of_range, invalid_argument…)
  • Có thể tự định nghĩa exception riêng bằng cách kế thừa từ std::exception
  • C++ không có finally - dùng RAII (smart pointer, destructor) để đảm bảo tài nguyên luôn được giải phóng đúng cách