try catch

try-catch 책임 경계

try 블록은 위험한 호출을 묶고 catch는 처리 가능한 실패만 잡는다. 너무 넓게 잡으면 원인 위치가 흐려지고, 너무 낮게 잡으면 정책이 흩어진다.

01

위험 구간을 묶는다

파일 열기, 파싱, 네트워크 호출처럼 실패 출처가 있는 코드를 try 안에 둔다.

02

구체 타입부터 잡는다

derived exception을 먼저 처리하고 마지막에 std::exception 참조로 공통 처리를 둔다.

03

정책을 실행한다

재시도, 기본값, 사용자 메시지, 프로그램 종료 중 어느 처리인지 catch 안에서 명확히 한다.

catch by const&
슬라이싱 방지 값으로 받으면 파생 예외 정보가 잘릴 수 있다.
대부분 const reference가 맞다.
catch 순서
좁은 타입 먼저 기반 타입을 먼저 잡으면 뒤의 파생 타입 catch는 도달하지 못한다.
컴파일러 경고를 확인한다.
throw;
현재 예외 재던짐 새로 throw e; 하면 타입 정보와 stack 문맥을 잃을 수 있다.
맥락 추가는 nested exception도 고려한다.
...
알 수 없는 실패 리소스 정리나 마지막 로그 후 다시 던지는 경우에 제한적으로 사용한다.
무조건 삼키면 디버깅이 어려워진다.

범위 · 순서 · 삼킴 점검

범위 try가 함수 전체를 감싸 원인과 복구 정책을 흐리게 하지 않는가.
순서 std::exception보다 구체적인 타입이 먼저 오는가.
삼킴 catch에서 아무 행동 없이 넘어가는 코드가 실제로 안전한가.

catch 순서

try {
    parse_file(path);
} catch (const ParseError& e) {
    show_line_error(e);
} catch (const std::exception& e) {
    log_error(e.what());
    throw;
}