예외처리
- 예외 상황, 예외 처리
- 예외처리 메커니즘
- Stack Unwinding
- 예외상황 표현하는 예외 클래스 설계
- 예외처리
예외 상황, 예외 처리
예외 상황
문법적 오류가 아닌 프로그램 논리에 맞지 않는 오류
ex) 나이 입력 : 0보다 작은 값 입력 -> 예외 상황
예외 처리
조건문을 통해 예외를 발견하고 처리가 가능하지만 이러한 방식은 예외처리부와 일반 코드를 쉽게 구분 불가
-> C++에서 별도 메커니즘 제공 : try, catch, throw
예외처리 메커니즘
try, catch, throw
try 블록에서 발생한 예외는 catch 블록에서 처리
try : 예외 발생의 검사 범위를 지정, 예외가 발생할 가능성이 있는 코드 블록
catch : try블록에서 발생한 예외를 처리, 예외 핸들러가 처리할 내용을 담은 코드 블록
throw : 예외의 발생을 알리는 역할, 오류에 대한 정보를 전달
-> try ~ catch문은 하나의 문장이므로 사이에 다른 문장 삽입 불가능
-> try문 실행 -> 예외 발생 : Catch 블록 실행 -> 예외 발생 없음 : try문 탈출
+ try블록 내부 : 예외 발생 시, 실행되면 안되는 코드 삽입
+ 예외 데이터 자료형 불일치 : 데이터의 전달만 이루어지고 처리는 되지 않음
+ ex) int Func(void) throw() { . . . } -> 어떠한 예외 상황도 발생하지 않는 함수라는 의미의 선언
1. try문 내의 코드 실행
2. 예외가 발생(throw) 하지 않으면 프로그램은 catch문 다음으로 이동
3. 예외가 발생하면 적절한 catch절을 찾게 됨
3-1. catch 핸들러는 스택에서 try문과 가장 가까운 catch문부터 차례대로 검사
3-2. 적절한 catch문을 발견하지 못하면 terminate() 함수 호출
4. 적절한 catch문을 발견하면 throw문의 피연산자는 예외 객체의 형식 매개변수로 전달
-> 양의 정수 입력 예외 처리
Stack Unwinding
예외가 처리 되지 않으면 예외가 발생한 함수를 호출한 영역으로 예외 전달
-> 예외는 처리될 때까지 계속 처리 : 처리 되지 못하면 비정상 종료
-> 예외 데이터가 상위로 전달되면 전달한 함수는 더 실행되지 않고 종료
Stack Unwinding(스택 풀기) : 예외를 처리하는 영역을 찾지 못해서 해당 예외가 상위 함수로 예외가 계속 전달
-> 함수 호출은 위 방향으로 스택이 쌓임 <-> 예외 데이터가 전달 : 역방향으로 스택이 해제
Func03() 함수에서 예외 발생
-> Func03() 에는 예외를 처리할 catch절이 없음 : Func02() 함수로 예외 전달
-> 스택에 저장되어 있던 Func03() 함수에 관한 스택 프레임을 모두 인출(pop)하고 Func02()함수로 이동
-> Func02() 함수에도 예외 처리 불가능 : Func01() 함수로 예외를 전달 : Func01() 함수도 처리 불가
-> Func01() 함수를 호출한 main()함수로 전달 : main()함수 내의 catch절에서 예외 처리 수행
예외 상황 표현하는 예외 클래스 설계
예외 객체
throw절에 사용되는 객체
-> 객체를 통해 예외 상황을 알리면 예외가 발생한 원인에 대한 정보를 자세히 담을 수 있음
예외 클래스
throw절에 사용되는 객체의 모델이 되는 클래스, 예외 클래스의 기초 클래스로 사용할 수 있는 클래스
-> 하나의 문자열 포인터를 반환하는 what()이라는 가상 멤버 함수를 제공
-> 해당 함수는 가상 함수이므로, exception 클래스로부터 파생된 클래스 내에서 재정의 가능
- 표준 예외 클래스
- stdexcept 헤더 파일을 통해 제공
- 논리 오류와 런타임 오류로 구분
- 헤더 파일은 logic_error, runtime_error
두 개의 클래스를 정의
-> logic_error
: 일반적인 논리 오류 처리
-> runtime_error
: 프로그램이 실행되는 동안 발생하는 오류 처리
- try문에서 정수형 예외 발생
- catch문에서 처리 불가
- set_terminate() 함수가 예외 처리
상속 관계 예외 클래스
유도 클래스는 기초 클래스의 포인터로 가리키거나 참조자로 참조 가능
-> 예외 클래스를 상속해주는 기초 클래스를 예외로 명시해주어도 유도 클래스로 받을 수 있음
예외 전달 방식 주의 사항
하나의 try 블럭에 여러 catch 블럭 사용 가능 : 맨 위의 catch 블록부터 하나씩 찾으면서 내려옴
예외처리
new 연산자 예외 처리
BadAlloc : new를 통해 메모리를 동적 할당하는 과정에서 할당에 실패하는 경우 발생하는 예외
-> 프로그래머가 예외 처리를 정의하지 않아도 예외 발생
모든 예외 처리
try { . . . }
catch { . . . }
-> 모든 예외를 처리
-> 발생한 예외와 관련한 어떠한 정보를 전달 받을 수 없으며, 전달된 예외의 종류 구분 불가능
예외 던지기
catch 블록에 전달된 예외는 다시 던질 수 있음 : 하나의 예외가 둘 이상의 catch 블록에 의해 처리
'Study > Passionate C++ Programming' 카테고리의 다른 글
[열혈 C++ 프로그래밍] 윤성우의 열혈 C++ 프로그래밍 내용 정리 (0) | 2024.02.10 |
---|---|
[열혈 C++ 프로그래밍] (16) C++ 형 변환자 (0) | 2024.02.10 |
[열혈 C++ 프로그래밍](14) 템플릿 2 (0) | 2024.02.10 |
[열혈 C++ 프로그래밍] (13) 템플릿 1 (1) | 2024.02.10 |
[열혈 C++ 프로그래밍] (12) String 클래스 디자인 (0) | 2024.02.10 |