(전체가 아니라 C#과 차이가 있는 부분을 중심으로 요약 정리)

에러와 예외

익셉션의 정체

익셉션이란 코드에서 발생한 ‘예외’ 상황이나 에러가 코드의 정상적인 실행 흐름에 퍼지지 않도록 알려주는 메커니즘이다. 익셉션 메커니즘을 적용하면 에러가 발생한 코드는 익셉션을 던지고(throw) 이를 처리하는 코드는 발생한 익셉션을 받아서 처리(catch) 하는 식으로 작동한다.

익셉션을 처리하는 과정은 기존 프로그램과 달리 순차적으로 실행되지 않는다. 어떤 코드가 익셉션을 던지면 프로그램의 정상 실행 흐름을 잠시 멈추고 익셉션 핸들러(exception handler, 예외처리기)로 제어권을 넘긴다.

이때 핸들러의 위치는 다양하다. 함수 바로 뒤에 나올 수도 있고, 연속된 함수 호출(스택 프레임)을 거슬러 올라가야 나올 수도 있다.

예컨대 아래 그림 14-1처럼 세 함수가 연달아 호출됐을 때 스택 상태를 살펴보자. 익셉션 핸들러가 있는 A()를 호출한 다음 B()를 호출하고, B()는 다시 C()를 호출했는데, C()에서 익셉션이 발생했다고 하자.

https://drive.google.com/uc?id=1UgnFQcuHLVEX7BqfZN96MtQklidOzBG_

위 그림 14-2는 핸들러가 익셉션을 받는 상황을 보여준다. 이 상태를 보면 C()와 B()에 대한 스택 프레임은 삭제됐고 A()에 대한 스택 프레임만 남았다.

C++에서 익셉션이 필요한 이유

기존에 작성된 C 또는 C++ 프로그램을 보면 에러를 처리하는 방식이 제각각이고 체계가 없는 경우가 많다. 함수가 정수 코드를 리턴하거나, errno 매크로를 사용해서 에러를 표시하는 것처럼 C 프로그래밍에서 표준처럼 굳어진 방식이 있는데, 이를 C++에 그대로 적용한 사례도 많다. 또한 스레드를 다룰 때 스레드의 로컬 정수 변수인 errno를 하나씩 만들어주고, 각 스레드가 함수를 호출하 측에 에러를 알려주는데 이 변수를 활용하기도 한다.

하지만 이렇게 정수 타입 리턴 코드나 errno를 사용하는 방식으로 구현하면 에러 처리 과정의 일관성을 유지하기 어렵다.

(예시 생략)

이처럼 일관성 없이 나름대로 정한 관례대로 구현한 함수들이 뒤섞이면 문제가 발생할 수 있다. 호출한 함수가 예상과 다른 방식으로 코드를 리턴하기 때문이다.

(이하 내용 생략)

익셉션 메커니즘을 사용하면 에러를 쉽고 일관성 있고 안전하게 처리할 수 있다. 기존에 C나 C++에서 활용하던 비공식 에러 처리 기법에 비해 익셉션 메커니즘이 뛰어난 점은 다음과 같다.

바람직한 에러 처리 방식