C++현대 C++

예외 처리 기본

오류를 호출 체인 위로 전달하는 `throw`, `try`, `catch`와 RAII의 관계를 정리합니다.

마지막 수정 2026년 3월 19일

기본 패턴

cpp
try {
    throw std::runtime_error("failed");
} catch (const std::exception& ex) {
    std::cout << ex.what() << "\n";
}

설명

  • 예외는 현재 함수가 직접 처리하기 어려운 오류를 호출자 쪽으로 전달하는 메커니즘입니다.
  • throw로 예외를 던지면 스택을 따라 올라가며 적절한 catch를 찾고, 그 과정에서 지역 객체들은 소멸자를 통해 정리됩니다.
  • 바로 이 점 때문에 C++에서 RAII가 중요한데, 예외가 발생해도 자원 정리가 자동으로 되도록 설계할 수 있기 때문입니다.
  • catch는 보통 const std::exception&처럼 참조로 받는 편이 복사 비용과 다형성 측면에서 유리합니다.
  • 예외는 강력하지만 제어 흐름을 숨길 수도 있으므로, "정말 예외 상황인가"와 "복구 가능한가"를 구분해 쓰는 편이 좋습니다.

짧은 예제

cpp
#include <exception>
#include <iostream>
#include <stdexcept>

int divide(int a, int b) {
    if (b == 0) {
        throw std::invalid_argument("division by zero");
    }
    return a / b;
}

int main() {
    try {
        std::cout << divide(10, 0) << "\n";
    } catch (const std::exception& ex) {
        std::cout << ex.what() << "\n";
    }
}

빠른 정리

항목설명
throw예외를 발생시킴
try예외 가능성이 있는 코드를 감쌈
catch특정 예외를 처리
stack unwinding예외 전파 중 지역 객체 소멸자가 호출됨
RAII 관계예외가 나도 자원 정리가 자동으로 되게 설계 가능

주의할 점

예외가 날 수 있는 코드에서 raw 자원을 직접 관리하면 누수가 생기기 쉽습니다. 예외 안전성을 확보하려면 스마트 포인터나 RAII 래퍼를 함께 쓰는 편이 좋습니다.