ProgramingTip

"예외를 사용하지 않는"캠프에있는 경우 표준 라이브러리를 어떻게 사용합니까?

bestdevel 2020. 12. 8. 19:22
반응형

"예외를 사용하지 않는"캠프에있는 경우 표준 라이브러리를 어떻게 사용합니까?


참고 : 나는 여기서 악마의 옹호자 나 그와 그의 역할을하는 것이 아닙니다. 저는 캠프에 있지 않기 때문에 진정으로 궁금합니다.

표준 라이브러리에있는 대부분의 유형에서 예외를 발생시킨 수있는 변형 함수 (예 : 메모리 할당에 실패한 경우) 또는 예외를 발생시키는 수있는 비 변형 함수 (예 : 범위를 벗어난 경우 접근 자)가 있습니다. 그 외에도 많은 무료 함수에서 예외를 던질 수 있습니다 (예 : operator newdynamic_cast<T&>).

"우리는 예외를 사용하지 않는다"맥락에서이를라는 실제로 어떻게 처리합니까?

  • 수있는 함수 던질 절대 호출 하지 않으려 고 합니까? (어떻게 확장 할 것인지 알 수있는 경우 어떻게 수행하는지 알 수 있습니다.)

  • 당신은 표준 라이브러리 던지기로 확인하고 당신은 "우리가 예외를 사용하지 않는" "는 결코 치료 우리 던져 에서 예외 우리의 코드와 우리가 결코 잡을 에서 예외 의 다른 코드를?"

  • 컴파일러 스위치를 통해 예외 처리를 모두 수행하고 있습니까? 표준 라이브러리의 예외 발생 부분은 작동 작동합니까?

  • 생성 편집 합니다. 실패 할 수 있습니까? 아니면 관례 적으로 실패시 오류 코드를 반환 할 수있는 생성을 사용하는 초기화 함수가있는 2 단계를 수행해야합니까?

편집 상의 의견과 증가 아래 질문에 대부분의 콘텐츠 일주 질문의 개시 후 마이너의 설명 ... 이유는 "뭔가 다른"VS 예외의 항목입니다. 내 관심사는 점에서 제외 할 당신이 "뭔가"를 선택이, 어떻게 당신은 표준 라이브러리 부품을 처리 할 할 할 예외를 처리 합니까?


나는 나 자신과 세상의 내 구석을 위해 대답 할 것이다. 나는 엄청난 양의 돈을 처리하고 절대 내려갈 수없는 지연 시간에 중요한 금융 앱을 c ​​++ 14 (컴파일러가 더 잘 지원하면 17 개가 될 것임)를 작성합니다. 규칙 세트는 다음과 가변됩니다.

  • 예외 없음
  • 아니 rtti
  • 작동 디스패치 없음
  • (거의) 상속 없음

할당 된 메모리가 풀링되고 사전에 초기화 후 malloc 호출이 없습니다. 데이터 구조는 영구적이거나 사소한 복사가 가능합니다. (스코프 가드와 거의 예외가 없음). 기본적으로 우리는 C + 유형 참석자 + 템플릿 + 람다를 수행하고 있습니다. 물론 예외는 컴파일러 스위치를 통해 활성화됩니다. STL의 경우 좋은 부분 (예 : 알고리즘, 숫자, 유형 _ 특성, 반복기, 원자, ...)을 모두 사용할 수 있습니다. 예외를 던지는 부분은 실행 메모리 할당 부분과 세미 OO 부분과 잘 일치하는 스트림, std :: array, std :: string을 사용하는 컨테이너를 한 번에 모두 제거 할 수 있습니다.

왜 이러나요?

  1. OO와 대회 예외는 문제를 다른 곳으로 숨기거나 이동하여 환상적이라면 제공하고 나머지 프로그램을 진단하기 어렵게 만듭니다. "-fno-exceptions"라고 할 때 모든 깔끔하고 잘 작동하는 함수는 실패 할 수 있는지 의심을 견뎌야합니다. 모든 작업을 실패하게 만드는 것보다 코드베이스 주변에서 광범위한 온 전성 검사를 수행하는 것보다.
  2. 예외는 기본적으로 지정되지 않은 목적지가있는 장거리입니다. longjmp ()를 사용하지 않을 경우는 훨씬 더 나쁩니다.
  3. 오류 코드가 우수하기 때문입니다. [[nodiscard]]를 사용하여 호출 코드를 강제로 확인할 수 있습니다.
  4. 예외 계층이 필요하지 않습니다. 대부분의 경우 오류를 구분하는 것은별로 의미가 있으며, 오류가 발생하는 경우에는 모든 신호를 처리하는 것이 훨씬 낫기 때문입니다.
  5. 유지해야 할 복잡한 불변성이 있기 때문입니다. 이 장 깊숙한 곳에 있더라도 초 국가적 보증이 필요하다는 것을 의미합니다. 이를 수행하는 방법에는 두 가지가 있습니다. 명령 적 절차를 가능한 한 순수하게 만들거나 (예 : 실패하지 않는지 확인) 불변 데이터 구조를 가지고 있습니다 (예 : 오류 복구를 가능하게 함). 변경 불가능한 데이터 구조를 사용할 경우 예외적으로 사용할 수 없습니다. 그러나 기능적 데이터 구조는 느리기 때문에 다른 대안은 순수한 함수를 가지고 C, C ++ 또는 Rust와 같은 예외없는 언어로 수행하는 것입니다. D가 아무리 예쁘지 않은 GC 및 예외가없는 옵션이 아닙니다.

  6. 명시적인 코드 경로처럼 예외를 테스트 한 적이 있습니까? "발생할 수없는"예외는 어떻습니까? 물론입니다. 실제로는 예외에 부딪히면 망가는 가공입니다.
  7. C ++에서 "아름다운"예외 중립 코드를 보았습니다. 즉, 호출하는 코드가 예외를 사용하는지 여부에 관계없이 에지 케이스없이 최적으로 수행됩니다. 모든 작성하기가 정말 어렵고 모든 예외를 유지하고 수정하기가 까다 롭습니다. 그러나 예외를 던지거나하는 "아름다운" 예외와 직접 상호 작용하는 모든 코드는 보편적으로 추악했습니다. 예외적 인 중립 코드를 작성하는 데 노력의 양은 예외를 던지거나하는 엉뚱한 코드에서 절약 한 양을 완전히 축소합니다. "아름다운"은 실제 아름다움이 아니기 때문에 따옴표로 묶여 있습니다. 편집에는 중립적 인 추가 부담이 필요하므로 일반적으로 화석화됩니다.

이 경우 컴파일러를 통해 예외를 발생시킵니다 (예 : -fno-exceptionsgcc).

gcc의 경우 _GLIBCXX_THROW_OR_ABORT다음과 같이 정의 된 매크로를 사용합니다.

#ifndef _GLIBCXX_THROW_OR_ABORT
# if __cpp_exceptions
#  define _GLIBCXX_THROW_OR_ABORT(_EXC) (throw (_EXC))
# else
#  define _GLIBCXX_THROW_OR_ABORT(_EXC) (__builtin_abort())
# endif
#endif

( libstdc++-v3/include/bits/c++config최신 gcc 버전 에서 박물관 수 있습니다 ).

그런 다음 예외가 중단되는 사실을 처리해야합니다. 여전히 신호를 처리하고 스택을 인쇄 할 수 있습니다 (발생하는 것을 설명하는 SO에 대한 좋은 답변이 있습니다), 종류의 일이 발생하는 것을 피하는 것이 좋습니다.

예를 들어보고 콘텐츠

try {
   Foo foo = mymap.at("foo");
   // ...
} catch (std::exception& e) {}

넌 할 수있어

auto it = mymap.find("foo");
if (it != mymap.end()) {
    Foo foo = it->second;
    // ...
}

또한 예외를 사용하지 않는 것에 대한 질문 할 때 표준 라이브러리에 대한 질문 이 있습니다 . "예외를 사용하지 않는"캠프 중 하나에있을 때 표준 라이브러리를 사용하고 있습니까?

표준 라이브러리는 무겁습니다. 예를 들어 많은 GameDev 회사와 같이 일부 "예외를 사용하지 않습니다"캠프에서는 STL에 더 적합한 대안이 사용됩니다. 대부분 EASTL 또는 TTL을 기반으로합니다. 이러한 라이브러리는 어쨌든 예외를 사용하지 않으며, 8 세대 콘솔이 예외를 너무 잘 처리하지 않았기 때문입니다 (또는 전혀). 최첨단 AAA 프로덕션 코드의 경우 어쨌든 예외가 너무 무겁기 때문에 이러한 경우에 윈-윈 시나리오입니다.

즉, 많은 프로그래머에게 예외를 끄는 것은 STL을 전혀 사용하지 않는 것과 짝을 이룹니다.


참고 예외를 사용합니다 ...하지만 강제로 사용하지 않았습니다.

던질 수있는 함수를 절대 호출하지 않으려 고합니까? (어떻게 확장되는지 알 수 없으므로이 경우 어떻게 수행하는지 듣고 싶습니다.)

이것은 적어도 대규모에서는 실행 불가능할 것입니다. 많은 함수가 발생하여 코드 기반을 완전히 손상시킬 수 있습니다.

표준 라이브러리 던지는 것에 동의하고 "우리는 예외를 사용하지 않는다"를 "우리 코드에서 예외를 던지지 않으며 다른 사람의 코드에서 예외를 포착하지 않는다"로 취급합니까?

당신은 그것에 대해 거의 괜찮을 것입니다. 만약 라이브러리 코드가 예외를 던질 것이고 당신의 코드가 그것을 처리하지 않을 것이라면, 종료는 기본 동작입니다.

컴파일러 스위치를 통해 예외 처리를 모두 비활성화하고 있습니까? 그렇다면 표준 라이브러리의 예외 발생 부분은 어떻게 작동합니까?

이것은 가능합니다 (예전에는 일부 프로젝트 유형에서 인기가있었습니다). 컴파일러는 이것을 지원하거나 지원할 수 있지만 결과가 무엇인지 (그리고 이러한 조건에서 지원되는 언어 기능)에 대해서는 해당 문서를 참조해야합니다.

일반적으로 예외가 발생하면 프로그램을 중단하거나 종료해야합니다. 일부 코딩 표준은 여전히이를 필요로합니다. JSF 코딩 표준이 떠 오릅니다 (IIRC).

"예외를 사용하지 않는"사람들을위한 일반적인 전략

대부분의 함수에는 호출하기 전에 확인할 수있는 사전 조건 세트가 있습니다 . 그것들을 확인하십시오. 만나지 않으면 전화하지 마십시오. 해당 코드에서 오류 처리가 무엇이든간에 폴백합니다. 전제 조건이 충족되었는지 확인할 수없는 기능의 경우 ...별로 프로그램이 중단 될 수 있습니다.

예외를 던지는 라이브러리피하는 방법을 찾을 수 있습니다. 표준 라이브러리의 맥락에서 이것을 요청했기 때문에 이것은 법안에 맞지 않지만 여전히 옵션입니다.

기타 가능한 전략 진부하게 들리지만 사용하지 않는 언어를 선택하십시오. C는 잘할 수 있습니다 ...

... 내 질문 (표준 라이브러리와의 상호 작용이 있다면)에 대해 나는 당신의 생성자에 대해 듣고 싶습니다. 실패 할 수 있습니까, 아니면 관례 적으로 실패시 오류 코드를 반환 할 수있는 전용 init 함수가있는 2 단계 생성을 사용합니까 (생성자가 할 수 없음)? 아니면 당신의 전략은 무엇입니까?

생성자가 사용되는 경우 일반적으로 실패를 표시하는 데 사용되는 두 가지 방법이 있습니다.

  1. 내부 오류 코드를 설정하거나 enum오류 및 오류를 표시합니다. 이것은 물체의 구성과 적절한 조치가 취해진 후에 조사 될 수 있습니다.
  2. 생성자를 사용하지 말고 (또는 적어도 생성자에서 실패 할 수없는 것을 생성하십시오-있다면) 그런 다음 init()일종의 메서드 를 사용하여 생성 을 수행하십시오 (또는 완료하십시오). 그러면 일부 실패가있는 경우 멤버 메소드가 오류를 리턴 할 수 있습니다.

init()기술 의 사용은 내부 "오류"코드보다 더 잘 연결되고 확장 될 수 있으므로 일반적으로 선호됩니다.

다시 말하지만, 이는 예외가 존재하지 않는 환경 (예 : C)에서 비롯된 기술입니다. 예외없이 C ++와 같은 언어를 사용하면 표준 라이브러리의 유용성과 유용성이 제한됩니다.


귀하가 요청한 질문에 완전히 대답하지 않고, 오류를 처리하는 메커니즘으로 예외를 사용하지 않는 코드 기반의 예로서 Google을 제공하겠습니다.

Google C ++ 코드베이스에서 실패 할 수있는 모든 함수 는 피 호출자의 결과를 지정하는 status것과 같은 메소드가 있는 객체를 반환합니다 ok.
개발자가 반환 status객체를 무시하면 컴파일이 실패하도록 GCC를 구성했습니다 .

또한 그들이 제공하는 작은 오픈 소스 코드 (예 : LevelDB 라이브러리)에서는 어쨌든 STL을 많이 사용하지 않는 것처럼 보이므로 예외 처리가 드뭅니다. Titus Winters가 CPPCon 강의에서 말했듯이, 그들은 "표준을 존중하되 우상화하지 마십시오".


나는 이것이 태도 질문이라고 생각합니다. 당신은 "무언가 실패해도 상관 없다"라는 캠프에 있어야합니다. 이로 인해 일반적으로 코드가 생성됩니다. 디버거 (고객 사이트에서)가 왜 갑자기 더 이상 작동하지 않는지 알아 내야합니다. 또한 이러한 방식으로 소프트웨어 "엔지니어링"을 수행하는 잠재적 인 사람들은 매우 복잡한 코드를 사용하지 않습니다. 예를 들어, 의존하는 모든 n 개의 리소스가 성공적으로 할당 된 경우에만 실행된다는 사실에 의존하는 코드를 작성할 수 없습니다 (이러한 리소스에 대해 RAII를 사용하는 동안). 따라서 이러한 코딩은 다음 중 하나를 초래합니다.

  • 오류 처리를위한 관리 할 수없는 양의 코드
  • 일부 리소스의 성공적인 할당에 의존하는 코드 실행을 피하기위한 관리 할 수없는 양의 코드
  • 오류 처리가 없으므로 상당한 지원 및 개발자 시간

Note, that I'm talking about modern code, loading customer-provided dlls on demand and using child processes. There are many interfaces on which something can fail. I'm not talking about some replacement for grep/more/ls/find.

참고URL : https://stackoverflow.com/questions/37700365/if-youre-in-the-we-dont-use-exceptions-camp-then-how-do-you-use-the-standar

반응형