2025/03/24 ch.14 에러처리
C++는 예상치 못한 예외적인 상황에 대처하도록 익셉션 이라는 기능을 제공한다.
예외상황 - 프로그램에서 발생할 가능성이 있는 잠재적인 문제들을 통틀어 부르는 말
C언어 - 에러 처리 기능을 직접 제공하지 않음
자바 - 언어에서 제공하는 익셉션메커니즘을 반드시 활용해서 프로그래밍하도록 강제함
C++ - 중간. 언어에서 익셉션 메커니즘을 제공하지만 반드시 사용할 필요는 없음
익셉션은 코드의 정상적인 실행 프름과는 별도로 실행됨.
에러가 발생하면 익셉션을 던지고, 이를 처리하는 코드는 발생한 익셉션을 받아서 처리. 순차적으로 실행되지 않음
익셉션을 던지면 프로그램의 정상 실행 흐름을 잠시 멈추고 익셉션 핸들러로 제어권을 넘긴다.
비공식 에러처리 방법보다 익셉션 메커니즘이 뛰어난 점
1. 에러를 리턴값으로 표현하면 호출한 측에서 깜박하고 리턴값을 검사하지 않거나 상위 함수로 전달하지 못할 수 있다.
2. 에러를 정수 타입 리턴 코드로 표현하면 구체적인 정보를 담기 힘들다.
3. 익셉션 메커니즘은 콜 스택의 중간 단계를 건너뛸 수 있다.
throw는 C++에 정의된 키워드, 익셉션을 던지려면 반드시 이 키워드를 사용해야 함.
표준 라이브러리에 정의된 익셉션은 일정한 계층을 형성하고 있다. 이 계층 구조에 속한 클래스마다 what() 메서드가 있는데, 이 메서드는 익셉션을 표현하는 const char* 스트링을 리턴함
14.2.2 익셉션 타입
던질 수 있는 익셉션의 타입에는 제한이 없다. 익셉션은 객체가 아니어도 된다.
하지만 기본 타입을 사용하기보다는 타입을 새로 정의하는 것이 바람직하다
- 객체는 클래스 이름에 예외 상황에 대한 정보를 드러낼 수 있다.
- 객체는 예외 상황의 종류 뿐만 아니라 다른 정보도 담을 수 있다.
14.2.3 익셉션 객체를 const 레퍼런스로 받기
익셉션 객체를 꼭const 레퍼런으소 받아야 한다는 법은 없다. 그냥 값이나 비 const 레퍼런스로 받아도 된다. 포인터로 받아도 된다.
# 익셉션 객체는 항상 const 레퍼런스로 받는것이 좋다. 익셉션 객체를 값으로 받으면 객체 슬라이싱이 발생하기 때문
14.2.4 여러 가지 익셉션 던지고 받기
<stdexcept> 의 runtime_error 익셉션 클래스 - 생성자를 호출할 때 익셉션에 대한 설명을 지정할 수 있다.
throw runtime_error { "error" };
이렇게 던지면 catch에서 what 메서드를 이용하여 받은 익셉션에 대한 정보를 확인한다.
try 블록에서 익셉션이 발생하면 컴파일러는 그 익셉션 타일과 일치하는 catch문을 선택힌다.
# 처리하려는 익셉션 타입에 대한 const 지정 여부는 매칭 과정에 영향을 미치지 않는다.
# catch 문에서 모든 종류의 익셉션에 매칭하려면 특수한 문법으로 작성한다.
try {}
catch(...) {}
... - 모든 익셉션 타입에 매칭하라는 와일드 카드
호출하는 함수에서 던지는 모든 익셉션을 받을 수 있어서 유용하긴 하지만 필요 없는 익셉션까지 처리하기 때문에 권장하지 않음
switch문의 default처럼 디폴트 캐치 핸들러를 구현할때 유용
14.2.5 처리하지 못한 익셉션
프로그램에서 발생한 익셉션을 처리하는 곳이 하나도 없으면 프로그램이 종료됨
main() 함수 전체를 try/catch 문으로 감싸는 패턴을 많이 사용함
terminate() 함수
내부적으로 abort() 함수를 호출해서 프로그램을 뻗게 만든다.
이런 콜백함수도 결국 에러를 무시하지 못하고 abort()나 _Exit() 로 프로그램을 종료시켜야 함. <- 객체의 소멸자가 호출되지 않는다.
#상용 소프트웨어를 구현할 때는 프로그램이 종료되기 전에 메모리 덤프를 생성하기 위해 terminate_handler를 설정하는 경우가 많다. 이렇게 생성된 메모리 덤프를 디버거에 입력하면 프로그램에서 놓친 익셉션이나 문제의 발생 원인을 알아낼 수 있다.
14.2.6 noexcept 지정자
함수가 던질 수 있는 익셉션의 종류에는 제한이 없다. noexcept 키워드로 어떠한 익셉션도 던지지 않는다고 선언할 수 있다.
이런 함수에 익셉션을 던지는 코드가 있으면 c++런타입은 terminate()를 호출해서 프로그램을 종료시킨다
742p