C_C++

C++ 예외처리 Exception Handling

고니자니 2024. 11. 20. 09:57
반응형

C++에서 예외 처리(Exception Handling)는 프로그램 실행 중 발생할 수 있는 예외적인 상황(에러)을 처리하기 위한 메커니즘입니다. 이를 통해 프로그램의 비정상 종료를 방지하고, 적절히 에러를 처리할 수 있습니다.

C++ 예외 처리는 주로 try, throw, catch 키워드를 사용하여 구현됩니다.

 

1. 기본 구조

try {
    // 예외가 발생할 가능성이 있는 코드
} catch (exception_type e) {
    // 예외 처리 코드
}

 

  • try: 예외가 발생할 가능성이 있는 코드를 작성하는 블록.
  • throw: 예외가 발생했을 때 예외 객체를 던지는 명령.
  • catch: 던져진 예외를 받아 처리하는 블록.

2. 간단한 예제

#include <iostream>

int main() {
    try {
        int a = 10, b = 0;
        if (b == 0) {
            throw "Division by zero error!";
        }
        std::cout << a / b << std::endl;
    } catch (const char* e) {
        std::cerr << "Exception: " << e << std::endl;
    }
    return 0;
}

 

(Output)

Exception: Division by zero error!

 

3. 다양한 예외 처리

(1) 여러 유형의 예외 처리

#include <iostream>

int main() {
    try {
        int choice = 1; // 예시로 변경 가능
        if (choice == 1) throw 404;           // 정수 예외
        if (choice == 2) throw "String error"; // 문자열 예외
        if (choice == 3) throw 3.14;          // 실수 예외
    } catch (int e) {
        std::cout << "Caught an integer: " << e << std::endl;
    } catch (const char* e) {
        std::cout << "Caught a string: " << e << std::endl;
    } catch (...) {
        std::cout << "Caught an unknown exception" << std::endl;
    }
    return 0;
}

...는 모든 예외를 처리하는 포괄적인 catch 블록입니다.

 

(2) 사용자 정의 예외

#include <iostream>
#include <stdexcept>

// 사용자 정의 예외 클래스
class MyException : public std::exception {
public:
    const char* what() const noexcept override {
        return "Custom exception occurred!";
    }
};

int main() {
    try {
        throw MyException(); // 사용자 정의 예외 던지기
    } catch (const MyException& e) {
        std::cout << e.what() << std::endl;
    } catch (...) {
        std::cout << "Unknown exception" << std::endl;
    }
    return 0;
}

 

 

  • std::exception 클래스를 상속하여 사용자 정의 예외를 구현합니다.
  • what() 메서드를 재정의하여 예외 메시지를 반환합니다.

 

4. 예외 발생 시 주의사항

(1) 스택 풀림(Stack Unwinding)

  • 예외가 발생하면, try 블록 내에서 생성된 객체는 자동으로 소멸합니다.
  • 이를 통해 메모리 누수를 방지할 수 있습니다.
#include <iostream>
using namespace std;

class Test {
public:
    Test() { cout << "Constructor called\n"; }
    ~Test() { cout << "Destructor called\n"; }
};

int main() {
    try {
        Test t;
        throw 1; // 예외 발생
    } catch (int e) {
        cout << "Exception caught: " << e << endl;
    }
    return 0;
}

 

(Output)

Constructor called

Destructor called

Exception caught: 1

 

(2) 예외 전달(Exception Propagation)

  • 예외가 발생했을 때, 적절한 catch 블록이 없다면 예외는 호출된 함수로 전달됩니다.
#include <iostream>
void func() {
    throw "An error occurred!";
}

int main() {
    try {
        func();
    } catch (const char* e) {
        std::cout << "Caught exception: " << e << std::endl;
    }
    return 0;
}

 

5. 표준 예외 클래스

C++ 표준 라이브러리는 std::exception을 포함한 다양한 예외 클래스를 제공합니다.

니다.

std::exception 모든 표준 예외의 기본 클래스.
std::runtime_error 런타임 에러 처리용.
std::logic_error 논리적 에러 처리용.
std::bad_alloc 메모리 할당 실패.
std::out_of_range 컨테이너 범위 초과.

 

예제: std::out_of_range

#include <iostream>
#include <vector>
#include <stdexcept>

int main() {
    try {
        std::vector<int> v = {1, 2, 3};
        std::cout << v.at(5) << std::endl; // 범위 초과
    } catch (const std::out_of_range& e) {
        std::cerr << "Out of range exception: " << e.what() << std::endl;
    }
    return 0;
}

(Output)

Out of range exception: vector::_M_range_check: __n (which is 5) >= this->size() (which is 3)

 

6. 예외 사용 시 유의점

  1. 예외는 예외적인 상황에서만 사용: 자주 발생하는 상황에서는 성능상 문제가 생길 수 있습니다.
  2. 자원 정리: RAII(Resource Acquisition Is Initialization) 패턴을 활용하여 자원 관리를 자동화하세요.
  3. 명확한 메시지 제공: 사용자 정의 예외를 활용할 경우 적절한 정보를 포함해야 디버깅이 용이합니다.

C++ 예외 처리는 코드 안정성을 높이는 데 매우 중요한 도구입니다. 잘 설계된 예외 처리는 프로그램을 더욱 견고하게 만들어줍니다.

 

반응형