에서는 C++의 장점은 무엇을 사용하여 예외를 시도/을 잡을 대신 그냥 돌아 오류 코드가?

StackOverflow https://stackoverflow.com/questions/196522

문제

나는 프로그래밍 C 및 C++오랜 시간이 지금까지 나는 결코 사용되는 예외를 시도/잡을 수 있습니다.의 장점은 무엇을 사용하는 대신 그는 기능을 갖는 오류 코드를 반환?

도움이 되었습니까?

해결책

아마도 명백한 요점 - 개발자는 귀하의 반품 상태를 무시하거나 알지 못할 수 있으며 무언가가 실패한 것을 행복하게 알지 못할 수 있습니다.

예외는 어떤 식 으로든 인정해야합니다. 적극적으로 무언가를 배치하지 않으면 조용히 무시할 수 없습니다.

다른 팁

의 장점 예외는 두 개의 접:

  • 그들은 무시할 수 없습니다. 해야 합격으로 그들과 함께 어떤 수준에서,또는 그들이 종료됩니다.오류 코드가 명시적으로 해야 합니다 확인을 위해 그들에게,또는 그들은 손실됩니다.

  • 그들은 무시할 수 있습니다. 오류가 발생한 경우할 수 없습으로 처리 수준에서 그것은 자동으로 거품 다음 수준까지,그것은이 될 수 있습니다.오류 코드가 명시적으로 전달되어야 합까지 그 수준에 도달하는 곳 그것으로 처리 될 수 있습니다.

장점은 잠재적으로 실패한 호출 후에 오류 코드를 확인할 필요가 없다는 것입니다. 이 작업을 수행하려면 스택이 풀릴 때 모든 것이 자동으로 정리되도록 RAII 클래스와 결합해야합니다.

오류 메시지 :

int DoSomeThings()
{
    int error = 0;
    HandleA hA;
    error = CreateAObject(&ha);
    if (error)
       goto cleanUpFailedA;

    HandleB hB;
    error = CreateBObjectWithA(hA, &hB);
    if (error)
       goto cleanUpFailedB;

    HandleC hC;
    error = CreateCObjectWithA(hB, &hC);
    if (error)
       goto cleanUpFailedC;

    ...

    cleanUpFailedC:
       DeleteCObject(hC);
    cleanUpFailedB:
       DeleteBObject(hB);
    cleanUpFailedA:
       DeleteAObject(hA);

    return error;
}

예외와 raii

void DoSomeThings()
{
    RAIIHandleA hA = CreateAObject();
    RAIIHandleB hB = CreateBObjectWithA(hA);
    RAIIHandleC hC = CreateCObjectWithB(hB);
    ...
}

struct RAIIHandleA
{
    HandleA Handle;
    RAIIHandleA(HandleA handle) : Handle(handle) {}
    ~RAIIHandleA() { DeleteAObject(Handle); }
}
...

언뜻보기에, RAII/예외 버전은 정리 코드를 한 번만 작성해야한다는 것을 깨달을 때까지 (그리고이를 단순화하는 방법이 있음) 더 길어 보인다. 그러나 복용량의 두 번째 버전은 훨씬 더 명확하고 유지 관리 가능합니다.

자원과 메모리를 유출하기 때문에 Raii 관용구없이 C ++에서 예외를 사용하지 마십시오. 모든 정리는 스택-할당 된 물체의 파괴자에서 수행해야합니다.

오류 코드 처리를 수행하는 다른 방법이 있다는 것을 알고 있지만 모두 다소 동일하게 보입니다. Gotos를 떨어 뜨리면 정리 코드를 반복하게됩니다.

오류 코드의 한 가지 요점은 사물이 실패 할 수있는 위치와 실패 방법을 분명하게 만든다는 것입니다. 위의 코드에서는 상황이 실패하지 않을 것이라는 가정으로 작성합니다 (그러나 그렇다면 Raii 포장지에 의해 보호됩니다). 그러나 당신은 결국 일이 잘못 될 수있는 곳에 대한 신념을 적게 지불하게됩니다.

예외 처리는 유기 때문에 그것은 쉽게 별도로 오류 처리하는 코드에서 작성된 코드를 처리하는 함수의 프로그램입니다.이것을 읽고 쓰는 코드는 쉽습니다.

언급 된 다른 것들 외에도 생성자의 오류 코드를 반환 할 수 없습니다. 파괴자들 중 하나이지만 소멸자로부터 예외를 던지지 않아야합니다.

  • 오류 코드를 반환하는 오류가 발생한 경우 조건 예상 어떤 경우에는
  • 할 때 예외를 발생한 오류 조건 에서 예상되는 어떤 경우

전자의 경우에는 발신자의 기능을 확인해야에 대한 오류 코드가 예상되는 장애;후자의 경우에는 예외 처리할 수 있습에 의해 호출 스택(또는 기본 처리기)를 적합한

나는 이것에 대한 블로그 항목을 썼다 (예외는 우아한 코드를 만듭니다), 이후에 출판되었습니다 초과 적재. 나는 실제로 Joel이 StackoverFlow 팟 캐스트에서 말한 것에 대한 응답으로 이것을 썼습니다!

어쨌든, 나는 대부분의 상황에서 예외가 오류 코드보다 바람직하다고 믿습니다. 오류 코드를 반환하는 함수를 사용하는 것이 정말로 고통 스럽습니다. 각 호출 후에 오류 코드를 확인해야하므로 호출 코드의 흐름을 방해 할 수 있습니다. 또한 오류를 알리는 방법이 없기 때문에 과부하 된 연산자를 사용할 수 없습니다.

오류 코드를 점검하는 고통은 사람들이 종종 그렇게하는 것을 소홀히하는 것을 의미합니다. catch 성명.

C ++에서 파괴자를 사용하고 .NET에서 처리기를 사용하여 예외가있을 때 리소스가 올바르게 풀리도록하면 코드를 크게 단순화 할 수 있습니다. 오류 코드로 동일한 수준의 보호를 얻으려면 많은 if 진술, 많은 복제 된 정리 코드, 또는 goto 함수 끝에 공통 정리 블록으로 호출됩니다. 이 옵션 중 어느 것도 즐겁지 않습니다.

여기에 있습니다 EAFP에 대한 좋은 설명 ( "허가보다 용서를 요청하기 쉽다"). Wikipedia의 Python 페이지 인 경우에도 여기에 적용됩니다. 예외를 사용하면보다 자연스러운 스타일의 코딩, IMO 및 많은 다른 사람들의 의견으로도됩니다.

내가 C ++를 가르치 곤했을 때, 우리의 표준 설명은 그들이 햇볕이 잘 드는 날과 비오는 날 시나리오를 방해하지 않도록 허용했다는 것입니다. 다시 말해, 모든 것이 잘 작동하는 것처럼 함수를 작성하고 결국 예외를 포착 할 수 있습니다.

예외 없이는 각 통화에서 반환 값을 얻고 여전히 합법적인지 확인해야합니다.

물론 관련 혜택은 예외에서 반환 값을 "폐기"하지 않는다는 것입니다 (따라서 무효가되어야하는 메소드가 무효가되도록하고 생성자 및 소멸자의 오류를 반환 할 수 있다는 것입니다.

Google의 C ++ 스타일 가이드 C ++ 코드에서 예외 사용의 장단점을 잘 분석합니다. 또한 요청해야 할 더 큰 질문 중 일부를 나타냅니다. 즉, 내 코드를 다른 사람에게 배포하려고합니까 (예외 가능 코드 기반과 통합하기가 어려울 수 있음)?

때로는 예외적 인 사례를 표시하려면 예외를 사용해야합니다. 예를 들어, 생성자에서 무언가 잘못되면 발신자에게 이것에 대해 알리는 것이 합리적이면 예외를 던질 수밖에 없습니다.

또 다른 예 : 때로는 함수가 오류를 나타 내기 위해 반환 할 수있는 값이 없습니다. 함수가 반환 할 수있는 값은 성공을 나타냅니다.

int divide(int a, int b)
{
    if( b == 0 )
        // then what?  no integer can be used for an error flag!
    else
        return a / b;
}

예외를 인정해야한다는 사실은 정확하지만 오류 스트러크를 사용하여 구현할 수도 있습니다. 특정 방법 (예 : ISOK)이 호출되었는지 여부를 DTOR에서 확인하는 기본 오류 클래스를 만들 수 있습니다. 그렇지 않다면, 당신은 무언가를 기록한 다음 종료하거나 예외를 던지거나 주장을 제기 할 수 있습니다.

오류에 반응하지 않고 오류 객체에서 ISOK를 호출하면 Catch (...) {} 작성과 동일합니다.

오류 코드를 올바른 수준까지 전송하는 것이 더 큰 관심사입니다. 기본적으로 거의 모든 방법이 전파의 유일한 이유에 대해 오류 코드를 반환해야합니다. 그러나 다시 함수 나 메소드는 항상 생성 할 수있는 예외로 주석을 달아야합니다. 따라서 기본적으로 당신은 그것을 지원하기 위해 인터페이스없이 동일한 문제가 필요합니다.

@Martin이 예외를 던지는 것을 지적하면서 프로그래머가 오류를 처리하도록 강요합니다. 예를 들어, 반환 코드를 확인하지 않으면 C 프로그램에서 가장 큰 보안 구멍이 있습니다. 예외는 오류를 처리하고 (희망적으로) 프로그램에 대한 일종의 복구 경로를 제공해야합니다. 보안 구멍을 소개하기보다는 예외를 무시하기로 선택한 경우 프로그램이 충돌합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top