C++가 말한다 “우리는 시도하고… 결국 집에 있다”

발행: (2025년 12월 28일 오후 03:42 GMT+9)
4 min read

Source: Hacker News

finally가 있는 언어들

예외를 지원하는 많은 언어¹는 finally 절도 제공하므로 다음과 같이 쓸 수 있습니다.

try {
    // stuff
} finally {
    always();
}

간단히 살펴보면 Java, C#, Python, JavaScript에는 이 제어 구조가 있지만 C++에는 없습니다.

C++은 “우리 집에 tryfinally가 있다”고 말합니다.

C++ 접근법

C++에서 블록을 빠져나갈 때 코드를 실행하려면 파괴자를 이용합니다. 파괴자는 블록을 떠날 때 실행되기 때문입니다. 이것이 Windows Implementation Library의 wil::scope_exit 함수가 사용하는 트릭입니다: 사용자가 제공한 람다를 파괴자에서 실행되는 사용자 정의 객체 안에 넣습니다.

auto ensure_cleanup = wil::scope_exit([&] { always(); });

/* stuff */

원리는 동일하지만, finally 혹은 파괴자 자체가 예외를 발생시켰을 때 각 언어가 이를 어떻게 처리하는지는 약간씩 차이가 있습니다.

예외 처리 의미론

예외 없이 보호된 블록을 빠져나가면, finally 블록이나 파괴자에서 발생한 잡히지 않은 예외는 try 블록에서 발생한 것으로 간주되어 다시 던져집니다. 모든 언어가 이 점에 동의하는 듯합니다.

예외와 함께 보호된 블록을 빠져나가고, finally 블록이나 파괴자도 예외를 발생시킨 경우, 동작은 언어마다 다릅니다.

Language두 개가 모두 예외를 던질 때 동작
Java, C#, JavaScriptfinally 블록에서 던진 예외가 원래 예외를 덮어쓰며, 원래 예외는 사라집니다.
Python (≥ 3.2)원래 예외가 새로운 예외의 context로 저장되지만, 전파되는 것은 새로운 예외입니다.
C++파괴자에서 예외가 발생하면, 그 파괴자가 이미 다른 예외 처리 중일 경우 자동으로 프로그램이 종료됩니다.¹

따라서 C++은 스코프를 떠날 때 코드를 실행할 수 있게 해 주지만, 예외가 빠져나가지 않도록 주의해야 합니다.

참고

¹ Microsoft 컴파일러는 구조화된 예외 처리(Structured Exception Handling)를 위해 __try__finally 키워드도 지원합니다. 이는 C 코드를 위한 것이며, C++에서 사용할 경우 C++ 예외와 혼동을 일으킬 수 있습니다. 자세한 내용은 Old New Thing에서 논의됩니다.

² 이 때문에 wil::scope_exit은 람다가 예외를 던지면 프로세스를 종료한다는 문서를 가지고 있습니다. 대안 함수인 wil::scope_exit_log는 람다에서 발생한 예외를 기록한 뒤 무시합니다. Java와 같은 동작을 제공하는 변형은 없습니다.

Back to Blog

관련 글

더 보기 »

C++가 “We have try at home”라고 말한다

다른 언어들의 finally 예외를 지원하는 많은 언어¹는 finally 절도 가지고 있어, 따라서 다음과 같이 쓸 수 있습니다. ```cpp try { // stuff } finally { always; } ``` 간단한 c...