try-catch문
예시 코드
try {
// 예외 발생 상황
if ()
throw ...
}
catch (...) { ... }
catch (...) { ... }
void customTerminate()
{
std::abort();
}
int main() {
// 예외처리가 없는 경우
std::set_terminate();
try {
// 예외를 발생시킬 수 있는 코드
int numerator = 10;
int denominator = 0;
if (denominator == 0) {
// 0으로 나누는 예외를 발생시킴
throw std::runtime_error("나누는 수가 0입니다.");
}
int result = numerator / denominator;
std::cout << "나눈 결과: " << result << std::endl;
}
catch (const std::exception& e) {
// 예외가 발생했을 때 실행되는 코드
std::cerr << "예외 발생: " << e.what() << std::endl;
}
return 0;
}
작동 방식
-
try 문 내의 코드를 실행
-
이때 예외가 발생(throw)하지 않으면 맨 마지막 catch 절 바로 다음으로 이동한다.
-
만약 예외가 발생하면 catch 핸들러는 다음 순서로 적절한 catch 절을 찾는다. (= 스택 풀기)
3-1. 스택에서 try 문과 가장 가까운 catch 절부터 차례대로 검사
3-2. 적절한 catch 절을 찾지 못하면, 바로 다음 바깥쪽 try 문 다음에 위치한 catch 절을 차례대로 검사
3-3. 이 과정을 가장 바깥쪽 try 문까지 계속 반복해서 검사.
3-4. 그래도 적절한 catch 절을 찾지 못하면, 미리 정의된 set_terminate() 함수가 호출됩니다.
-
만약 적절한 catch 절을 찾게 되면, throw 문 뒤의 변수/객체를 catch문의 매개변수로 전달
-
모든 예외 처리가 끝나면 프로그램의 제어는 맨 마지막 catch 절 바로 다음으로 이동
terminate()
std::terminate() 함수는 예외가 처리되지 않고 호출 스택을 거슬러 올라가 예외 처리가 가능한 catch 블록을 찾지 못했을 때 호출되는 함수다. 자동으로
이 함수는 기본적으로 예외를 처리할 수 없는 상황에서 프로그램을 종료시키는 역할을 한다.
만약 사용자가 terminate() 함수를 임의로 만들고 싶다면 set_terminate() 함수를 적고, 파라미터로 어떤 동작을 할지 정해줄 함수의 포인터를 넣어주면 된다.
exception 클래스
무엇을 throw 할 것인가?
- 기본 자료형을 throw 해도 된다. 그러나 어떤 예외인지를 표현하는데 있어 한계가 있다.
- 그래서 throw 전용 객체를 만들어줬는데, 이 객체의 타입이 바로 exception (예외) 클래스 이다.
exception 클래스의 구성
1. what()이라는 멤버 함수를 제공
- what() 자체는 가상함수
- 따라서 자식함수에서 재정의해서 무엇을 출력할지 정의할 수 있음.
2. exception 자체를 직접 쓰지 않고, exception의 자식 클래스를 씀.
- 대표적인 자식 클래스 : logic_error, runtime_error 등등...
- 사용자가 직접 자식 클래스를 만들 수도 있음.
what()은 다음과 같이 생겼다.
// 예전 방식 (C++98, C++03)
virtual const char *what() const throw();
// 최신 방식 (C++11 이후)
virtual const char *what() const noexcept;
// 맨 뒤 throw()나 noexcept는 이 함수가 예외를 던지지 않음을 의미.