콘텐츠로 이동

예외 (Exceptions)

우리는 C++ 예외를 사용하지 않습니다.

  • 예외를 사용하면 모호하고 오류가 발생하기 쉬운 오류 코드 장부를 작성하지 않고도 상위 수준의 애플리케이션이 깊게 중첩된 함수에서 "발생할 수 없는" 오류를 처리하는 방법을 결정할 수 있습니다.
  • 일부 타사 C++ 라이브러리는 예외를 사용하므로 내부적으로 예외를 끄면 해당 라이브러리와 통합하기가 더 어려워집니다.
  • 예외는 생성자가 실패하는 유일한 방법입니다. 팩토리 함수나 Init() 메서드를 사용하여 이를 시뮬레이션할 수 있지만 각각 힙 할당이나 새로운 "유효하지 않은" 상태가 필요합니다.
  • 예외는 프레임워크를 테스트할 때 정말 편리합니다.

  • 기존 함수에 throw 문을 추가하는 경우 모든 전이 호출자를 검사해야 합니다. 최소한 기본적인 예외 안전을 보장해야 하거나, 예외를 포착해서는 안 되고 결과적으로 프로그램이 종료되는 것에 만족해야 합니다. 예를 들어 f()가 g()를 호출하고 h()를 호출하고 h가 f를 포착하는 예외를 발생시키는 경우 g는 주의해야 합니다. 그렇지 않으면 제대로 정리되지 않을 수 있습니다.

  • 보다 일반적으로 예외는 코드를 보고 프로그램의 제어 흐름을 평가하기 어렵게 만듭니다. 즉, 함수가 예상하지 못한 위치에서 반환될 수 있습니다. 이로 인해 유지 관리 및 디버깅이 어려워집니다. 예외를 사용할 수 있는 방법과 위치에 대한 몇 가지 규칙을 통해 이 비용을 최소화할 수 있지만, 개발자가 알고 이해해야 하는 비용이 더 커집니다.
  • 예외 안전에는 RAII와 다양한 코딩 방법이 모두 필요합니다. 올바른 예외 안전 코드를 쉽게 작성하려면 많은 지원 기계가 필요합니다. 또한 독자가 전체 호출 그래프를 이해하도록 요구하지 않으려면 예외로부터 안전한 코드는 지속 상태에 쓰는 논리를 "커밋" 단계로 격리해야 합니다. 이렇게 하면 이점과 비용이 모두 발생합니다(커밋을 격리하기 위해 코드를 난독화해야 하는 경우가 있을 수 있음). 예외를 허용하면 그럴 가치가 없는 경우에도 항상 해당 비용을 지불해야 합니다.
  • 예외를 설정하면 생성된 각 바이너리에 데이터가 추가되어 컴파일 시간이 약간 증가하고 주소 공간 압박이 증가할 수 있습니다.
  • 예외의 가용성은 개발자가 적절하지 않을 때 예외를 던지거나 그렇게 하는 것이 안전하지 않을 때 예외를 복구하도록 장려할 수 있습니다. 예를 들어 잘못된 사용자 입력으로 인해 예외가 발생해서는 안 됩니다. 이러한 제한 사항을 문서화하려면 스타일 가이드를 더 길게 만들어야 합니다!

표면적으로는 예외를 사용함으로써 얻을 수 있는 이점이 비용보다 더 큽니다. 특히 새 프로젝트에서는 더욱 그렇습니다. 그러나 기존 코드의 경우 예외가 도입되면 모든 종속 코드에 영향을 미칩니다. 예외가 새 프로젝트 외부로 전파될 수 있는 경우 새 프로젝트를 기존 예외 없는 코드에 통합하는 것도 문제가 됩니다. Google의 기존 C++ 코드 대부분은 예외를 처리할 준비가 되어 있지 않기 때문에 예외를 생성하는 새로운 코드를 채택하는 것은 비교적 어렵습니다.

Google의 기존 코드가 예외를 허용하지 않는다는 점을 고려하면 예외를 사용하는 데 드는 비용은 새 프로젝트의 비용보다 다소 높습니다. 변환 프로세스는 느리고 오류가 발생하기 쉽습니다. 우리는 오류 코드 및 주장과 같은 예외에 대한 사용 가능한 대안이 상당한 부담을 초래한다고 믿지 않습니다.

예외 사용에 대한 우리의 조언은 철학적 또는 도덕적 근거가 아니라 실제적인 근거에 근거합니다. 우리는 Google에서 오픈 소스 프로젝트를 사용하고 싶지만 해당 프로젝트에서 예외를 사용하는 경우 사용하기 어렵기 때문에 Google 오픈 소스 프로젝트에서도 예외에 대해 조언할 필요가 있습니다. 처음부터 다시 시작해야 한다면 상황이 달라졌을 것입니다.

이 금지 사항은 std::exception_ptrstd::nested_exception과 같은 예외 처리 관련 기능에도 적용됩니다.

Windows 코드에는 이 규칙에 대한 예외가 있습니다(말장난 의도 없음).


이해하기 쉽게 설명하기

핵심: Google C++ 코드에서는 예외를 쓰지 않는다

이 결정은 철학이 아니라 실용적 이유에 근거합니다. Google의 기존 C++ 코드 대부분이 예외를 처리할 준비가 되어 있지 않아, 예외를 던지는 새 코드를 섞으면 모든 의존 코드에 영향을 주고 통합이 어려워집니다.

왜 (이론적 장점에도 불구하고) 막는가?

  • 새 함수에 throw를 넣으면 모든 전이 호출자가 최소한의 예외 안전성을 보장해야 합니다.
  • 예외는 제어 흐름을 보이지 않게 만들어(예상치 못한 지점에서 반환) 유지보수·디버깅을 어렵게 합니다.
  • 예외 안전 코드는 RAII와 "커밋 단계 격리" 같은 추가 장치를 요구하며, 그 비용은 예외를 안 쓰는 코드도 늘 떠안게 됩니다.

범위와 예외

  • std::exception_ptr, std::nested_exception 같은 예외 관련 기능도 금지에 포함됩니다.
  • 새 프로젝트만 놓고 보면 장점이 더 클 수 있지만, 기존 코드베이스와의 호환성 때문에 일관되게 금지합니다.
  • 단, Windows 코드에는 이 규칙의 예외가 있습니다.