[C/C++] 예외 처리(Exception Handling)

할랑말랑·2026년 3월 11일

C/C++

목록 보기
16/45

예외 처리(Exception Handling)

예외는 프로그램 실행 중 발생하는 오류나 비정상적인 상황이다.
예외 처리는 예외가 발생했을 때 이를 처리하여 프로그램이 비정상적으로 종료 대신 안전하게 수습하는 방식

1. 예외 처리의 기본 요소

  • throw : 예외를 발생시키는 키워드, 특정 조건에서 예외를 던져 호출자에게 알린다.
  • try : 예외가 발생할 가능성이 있는 코드를 감싸는 블록이다. 이 블록 안에서 예외가 발생하면, 해당 예외는 catch 블록으로 전달된다.
  • catch : 발생한 예외를 처리하는 블록이다. 특정 예외 타입에 따라 다르게 처리할 수 있다.

2. 예외 처리의 흐름

  • 예외 발생 : 함수 내에서 throw를 사용하여 예외를 발생시킨다.
  • 예외 감지 : 예외가 발생하면 프로그램은 try 블록을 종료하고 해당 예외를 처리할 수 있는 catch 블록을 찾는다.
  • 예외 처리 : catch 블록이 예외를 받아서 처리한다.
#include <iostream>
#include <stdexcept>

using namespace std;

void riskyFunction()
{
    throw std::runtime_error("An error occurred!");
}

int main()
{
    try
    {
        riskyFunction();  // 예외 발생 가능
    }
    catch (const std::runtime_error& e)
    {
        std::cerr << "Caught an exception: " << e.what() << std::endl;  // 예외 처리
    }

    return 0;
}
  • stdexcept : C++ 표준 라이브러리에서 논리 오류(logic_error)와 런타임 오류(runtime_error)를 보고하는 표준 예외 클래스들을 정의하는 헤더 파일이다
  • std::runtime_error()를 사용하여 새로운 예외 객체를 생성한다.(문자열 인자 - 예외를 처리할때 어떤 예외가 발생했는지 알릴때 사용하는 메시지)
  • std::runtime_error 클래스에서 제공하는 what() 함수를 호출하면 예외 발생 시 전달된 메시지를 반환한다. 이를 통해 어떤 문제가 발생했는지 알 수 있다.

3. noexcept

noexcept 지정자는 C++11로부터 도입된 키워드로, 함수나 연산자가 예외(exception)를 던지지 않음을 나타내는 데 사용된다.

이 키워드를 사용하여 함수 선언 앞에 붙이면, 해당 함수가 예외를 던지지 않음을 보장합니다.

noexcept로 선언된 함수는 예외를 던지지 않기 때문에 컴파일러는 더 많은 최적화를 할 수 있다.

만약 noexcept로 선언된 함수에서 예외가 발생하면, 프로그램은 즉시 종료된다.

void safeFunction() noexcept
{
    std::cout << "This function is safe and will not throw." << std::endl;
}

핵심 최적화 및 활용

  • 최적화 원리
    런타임 검사 코드 생략 : 컴파일러는 예외를 처리하기 위한 런타임 검사 코드(예: 예외 핸들러)를 생성하지 않아도 되므로, 코드 크기가 작아지고 실행 속도가 빨라집니다.

  • 성능 향상
    표준 라이브러리 컨테이너 - 예를 들어 vector과 같은 컨테이너는 요소를 이동할때 noexcept가 붙은 이동 생성자를 사용하여 성능을 향상시킨다.
    재할당 시 예외가 발생하지 않을 것이라고 보장되므로, 더 효율적으로 메모리 이동 및 재배치를 수행할 수 있다.

권장 대상

  • 이동 생성자 : 객체의 자원을 안전하게 이동할 수 있도록 설계되며, 예외를 던지지 않도록 noexcept를 붙이는 것이 좋다.
  • 이동 대입 연산자 : 기존 객체의 자원을 새로운 객체로 이동할 때 사용되며, 마찬가지로 noexcept를 붙이는 것이 좋다.
  • swap() 함수 : 두 객체의 내용을 빠르게 교환하는 함수는 예외를 발생시키지 않도록 설계하고 noexcept를 붙이는 것이 좋다.
  • 소멸자 : 객체의 자원을 해제하는 소멸자도 예외를 던지지 않도록 설계되어야 하고 noexcept를 사용하는 것이 일반적인 권장 사항이다.

예외 발생 시 비정상 종료

noexcept로 선언된 함수에서 실제로 예외가 발생하면, std::terminate()가 호출되어 프로그램이 비정상적으로 종료된다.

따라서, 예외 발생 가능성이 없는 함수에만 신중하게 noexcept를 사용해야 한다. 예외가 발생할 수 있는 로직을 포함한 함수에서 noexcept를 사용하는 것은 매우 위험하다.

0개의 댓글