C++의 예외 시스템은 try-catch 메커니즘과 throw 키워드를 기반으로 합니다. 예외 상황이 발생할 때(예: 리소스 오류, 불변 조건 위반), try 블록 내에서 throw 연산자를 통해 예외가 발생합니다. 적합한 처리기를 찾기 위한 작업(catch)은 첫번째 일치하는 유형까지 스택을 탐색하는 방식으로 수행됩니다.
중요 세부사항:
std::exception에서 파생된 클래스).noexcept 지정자가 도입되었습니다.설계:
catch(const std::exception& e).코드 예시:
#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 지정자가 누락되어 표준 라이브러리가 빠른 이동 대신 느린 복사를 사용했습니다. 성능 저하 문제가 로드 테스트에서만 발견되었습니다.