프로그래밍C++ 백엔드 개발자

C++에서 예외 시스템(예외 처리는 어떻게 작동하며 다른 언어와 어떤 차이가 있나요? 산업 응용 프로그램에서 예외 처리 설계를 어떻게 해야 하나요?

Hintsage AI 어시스턴트로 면접 통과

답변

C++의 예외 시스템은 try-catch 메커니즘과 throw 키워드를 기반으로 합니다. 예외 상황이 발생할 때(예: 리소스 오류, 불변 조건 위반), try 블록 내에서 throw 연산자를 통해 예외가 발생합니다. 적합한 처리기를 찾기 위한 작업(catch)은 첫번째 일치하는 유형까지 스택을 탐색하는 방식으로 수행됩니다.

중요 세부사항:

  • Java나 C#와 달리 C++에서는 예외가 어떤 유형이든 될 수 있습니다(일반적으로 std::exception에서 파생된 클래스).
  • C++에는 예외 사양이 필수가 아닙니다(예: Java의 checked exceptions). 대신 C++11 이후 noexcept 지정자가 도입되었습니다.
  • 예외를 던질 때는 발생 지점과 처리 지점 사이의 모든 객체의 소멸자가 호출됩니다 — RAII를 지켜야 합니다.

설계:

  • "예기치 않은" 오류에 대해서만 예외를 던지고, 나머지 상황에서는 반환 코드를 사용하세요.
  • 상수 참조로 잡아야 합니다 — catch(const std::exception& e).
  • GNU는 포인터 대신 복사 가능한 객체를 던질 것을 권장합니다(힙 메모리를 피하십시오).

코드 예시:

#include <iostream> #include <stdexcept> void mayFail(bool fail) { if (fail) throw std::runtime_error("프로세스 오류"); } int main() { try { mayFail(true); } catch (const std::exception& ex) { std::cout << "포착된 예외: " << ex.what() << std::endl; } }

트릭 질문

예외가 다른 예외를 처리하는 동안 소멸자에서 발생하면 어떻게 되나요?

답변: 프로그램이 std::terminate()를 호출하여 비정상 종료됩니다. 예외 처리 중에 새로운 예외를 발생시키는 것은 금지되며(이중 예외), 이는 스택 언와인딩을 방해하기 때문입니다.

예시:

struct CrashOnDestruct { ~CrashOnDestruct() noexcept(false) { throw std::runtime_error("소멸자에서 오류 발생!"); } }; void func() { CrashOnDestruct obj; throw std::logic_error("오류 처리"); } int main() { try { func(); } catch (...) { } } // std::terminate()로 종료됩니다.

주제에 대한 세부적인 지식 부족으로 인한 실제 오류 사례들


이야기

대규모 금융 애플리케이션 내에서 예외가 데이터베이스 클래스 래퍼의 소멸자에서 발생했습니다. 오류가 발생할 때 주요 트랜잭션이 예외를 발생시켰고, unwind 시 소멸자가 호출되었으며, 다시 오류를 던졌습니다. 전체 애플리케이션이 비정상적으로 종료되었고 사용자 작업이 손실되었습니다. 개발자들은 소멸자에서 throw를 로그 기록 및 올바른 처리로 신속하게 변경해야 했습니다.


이야기

마이크로서비스가 예외를 catch(std::exception)으로 처리했습니다. 한 스레드가 사용자 정의 유형의 예외를 던졌지만(std::exception에서 상속되지 않음), 이러한 오류는 잡히지 않았고 예기치 않은 연결 종료 및 메모리 누수가 발생했습니다.


이야기

컨테이너 이동 메서드에 noexcept 지정자가 누락되어 표준 라이브러리가 빠른 이동 대신 느린 복사를 사용했습니다. 성능 저하 문제가 로드 테스트에서만 발견되었습니다.