Namespaces
Variants

Exceptions

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

예외 처리(exception handling)는 프로그램 실행 중 특정 지점에서 제어와 정보를 전달하는 방법을 제공하며, 이는 실행 과정에서 이전에 통과한 지점과 연결된 핸들러(handler)로 전달됩니다(다시 말해, 예외 처리는 호출 스택(call stack)을 따라 제어를 상위로 전달합니다).

throw 표현식 을 평가하면 예외가 발생합니다. 예외는 다른 상황 에서도 발생할 수 있습니다.

예외가 잡히기 위해서는 throw 표현식이 try block 내부에 있어야 하며, try 블록은 예외 객체의 타입과 일치하는 handler 를 포함해야 합니다.

함수를 선언할 때, 함수가 던질 수 있는 예외의 유형을 제한하기 위해 다음 명세(specification)를 제공할 수 있습니다:

(C++17까지)
(C++11부터)

예외 처리 중 발생하는 오류는 std::terminate std::unexpected (C++17까지) 에 의해 처리됩니다.

목차

사용법

throw 표현식은 실행 스택 상의 임의의 코드 블록으로 제어를 전달하는 데 사용될 수 있지만(이는 std::longjmp 와 유사합니다), 이것의 주된 사용 목적은 오류 처리입니다.

오류 처리

예외를 던지는 것은 함수에서 오류를 신호하는 데 사용되며, "오류"는 일반적으로 다음으로만 제한됩니다 [1] [2] [3] :

  1. 사후 조건을 충족하지 못하는 경우, 예를 들어 유효한 반환 값 객체를 생성하지 못하는 경우.
  2. 호출해야 하는 다른 함수의 사전 조건을 충족하지 못하는 경우.
  3. (비공개 멤버 함수가 아닌 경우) 클래스 불변식을 (재)설립하지 못하는 경우.

특히, 이는 생성자의 실패(또한 RAII 참조)와 대부분의 연산자의 실패가 예외를 던짐으로써 보고되어야 함을 의미합니다.

또한, 소위 wide contract 함수들은 허용되지 않는 입력을 나타내기 위해 예외를 사용합니다. 예를 들어, std::basic_string::at 함수는 사전 조건이 없지만 인덱스가 범위를 벗어났음을 나타내기 위해 예외를 던집니다.

예외 안전성

함수가 오류 조건을 보고한 후, 프로그램의 상태와 관련하여 추가적인 보장이 제공될 수 있습니다. 일반적으로 인정되는 다음 네 가지 수준의 예외 보장은 서로 엄격한 상위 집합 관계에 있습니다: [4] [5] [6]

  1. Nothrow(또는 nofail) 예외 보장 — 함수가 예외를 절대 던지지 않습니다. Nothrow(오류는 다른 방법으로 보고되거나 숨겨짐)는 소멸자 와 스택 풀기 중에 호출될 수 있는 다른 함수들에 기대됩니다. 소멸자 들은 기본적으로 noexcept 입니다. (C++11부터) Nofail(함수가 항상 성공함)는 swap 연산, 이동 생성자 , 그리고 강력한 예외 보장을 제공하는 함수들이 사용하는 다른 함수들에 기대됩니다.
  2. 강력한 예외 보장 — 함수가 예외를 던지면, 프로그램의 상태는 함수 호출 직전의 상태로 롤백됩니다(예: std::vector::push_back ).
  3. 기본 예외 보장 — 함수가 예외를 던지면, 프로그램은 유효한 상태에 있습니다. 자원 누수가 발생하지 않으며, 모든 객체의 불변식이 유지됩니다.
  4. 예외 보장 없음 — 함수가 예외를 던지면, 프로그램이 유효한 상태에 있지 않을 수 있습니다: 자원 누수, 메모리 손상, 또는 다른 불변식 파괴 오류가 발생했을 수 있습니다.

제네릭 컴포넌트는 추가적으로 예외 중립 보장(exception-neutral guarantee) 을 제공할 수 있습니다: 템플릿 매개변수에서 예외가 발생하는 경우(예: std::sort Compare 함수 객체나 std::make_shared 에서 T 의 생성자에서 예외가 발생하는 경우), 이 예외는 변경되지 않은 상태로 호출자에게 전파됩니다.

예외 객체

모든 완전한 타입의 객체와 cv void 포인터는 예외 객체로 던져질 수 있지만, 모든 표준 라이브러리 함수는 이름 없는 객체를 값으로 던지며, 그 객체들의 타입은 (직접적 또는 간접적으로) std::exception 에서 파생됩니다. 사용자 정의 예외는 일반적으로 이 패턴을 따릅니다. [7] [8] [9]

불필요한 예외 객체 복사와 객체 슬라이싱을 방지하기 위해, 핸들러는 참조로 예외를 catch하는 것이 가장 좋은 방법입니다. [10] [11] [12] [13]

참고 사항

기능 테스트 매크로 표준 기능
__cpp_constexpr_exceptions 202411L (C++26) constexpr 예외

외부 링크

  1. H. Sutter (2004) "When and How to Use Exceptions" Dr. Dobb's 저널
  2. H. Sutter, A. Alexandrescu (2004), "C++ Coding Standards", 항목 70
  3. C++ 핵심 가이드라인 I.10: 필수 작업 수행 실패를 알리기 위해 예외를 사용하라
  4. B. Stroustrup (2000), "The C++ Programming Language" 부록 E
  5. H. Sutter (2000) "Exceptional C++"
  6. D. Abrahams (2001) "Exception Safety in Generic Components"
  7. D. Abrahams (2001) "Error and Exception Handling"
  8. isocpp.org Super-FAQ "What should I throw?"
  9. C++ 핵심 가이드라인 E.14: 예외로 기본 제공 타입이 아닌 목적에 맞게 설계된 사용자 정의 타입을 사용하라
  10. C++ 핵심 가이드라인 E.15: 값으로 던지고, 계층 구조의 예외는 참조로 잡아라
  11. S. Meyers (1996) "More Effective C++" 항목 13
  12. isocpp.org Super-FAQ "What should I catch?"
  13. H. Sutter, A. Alexandrescu (2004) "C++ Coding Standards" 항목 73