예외 정책

예외와 자원 정리

예외를 쓰느냐 return code를 쓰느냐는 취향 문제가 아니다. 호출자가 복구할 수 있는 실패인지, 스택을 건너뛰어도 RAII로 자원이 정리되는지, noexcept, C ABI, thread entry 밖으로 예외를 흘려도 되는지가 함께 결정되어야 한다.

01

실패 성격 분류

파일 없음, 입력 오류, 메모리 부족, precondition 위반을 같은 방식으로 다루지 않는다.

recoverable 실패만 호출자에게 올린다
02

자원 소유 확인

lock_guard, file handle, socket, memory가 스택 해제 중 RAII 객체로 정리되는지 본다.

manual cleanup보다 소유 타입을 둔다
03

보장 수준 결정

실패 후 상태가 그대로인지 strong, 유효하지만 바뀔 수 있는지 basic, 던지지 않는지 nothrow를 정한다.

copy-and-swap으로 rollback 지점을 만든다
04

경계에서 변환

스레드 시작점, C API, 소멸자, 이벤트 콜백에서는 예외를 잡아 error code, 로그, exception_ptr로 바꾼다.

ABI와 thread entry에서는 translate한다
05

로그와 문서화

던지는 타입, noexcept 여부, 복구 전략, 호출자 책임을 API 문서에 남긴다.

context 없는 catch(...)는 원인을 지운다
exception
드문 실패와 스택 전파 즉시 처리할 수 없는 오류를 RAII 정리와 함께 호출 경계까지 올릴 때 적합하다.
loop/if 대용 throw는 피한다
expected/code
즉시 분기와 예상 실패 호출자가 바로 확인하고 다른 경로를 선택할 수 있을 때 std::expected나 error code가 명확하다.
[[nodiscard]] wrapper로 누락을 막는다
RAII
소멸자 정리 경로 스택을 빠져나가도 소유 객체의 소멸자가 자원을 닫는다.
destructor는 throw를 삼키거나 기록한다
경계
전파 금지 지점 thread entry, noexcept 함수, C ABI, destructor에서 예외를 잡아야 한다.
translate 없으면 std::terminate가 된다

catch 블록의 복구·재던지기 계약

handler ownership catch가 재시도·대체값·상위 전파 중 하나를 책임지는지 본다.
RAII ownership 예외 발생 지점 뒤 close, unlock, delete가 소유 객체로 흡수됐는지 확인한다.
ABI/thread fence 스레드, 콜백, C ABI, noexcept 경계에서 예외가 error code나 exception_ptr로 변환되는지 본다.