"try"- "catch"에서 모든 블록을 래핑해서는 안되는 이유는 무엇입니까?


430

나는 항상 메소드가 예외를 던질 수 있다면 의미있는 try 블록 으로이 호출을 보호하지 않는 것이 무모하다는 것을 항상 믿었습니다.

난 그냥 '게시 시도, 캐치 블록을 던질 수있는 통화를 포장해야합니다. ' 이 질문에 대해 '매우 나쁜 조언 '이라고 들었습니다. 이유를 이해하고 싶습니다.


4
메소드가 예외를 던질 것이라는 것을 알았다면, 나는 그것을 먼저 수정했을 것입니다. 어디서 그리고 왜 코드가 소스에서 예외를 잡아야하는지 (각 방법-하나의 일반적인 try-catch) 예외를 던질 이유를 알 수 없기 때문입니다. 예를 들어 한 팀이 이전 데이터베이스가있는 코드 기반을 제공했습니다. SQL 계층에서 try catch를 추가 한 후에 만 ​​많은 열이 누락되고 포착되었습니다. 둘째로 오프라인 디버깅을 위해 메소드 이름과 메시지를 기록 할 수 있습니다. 그렇지 않으면 메소드의 출처를 모릅니다.
차크라

답변:


340

적절한 방법으로 처리 할 수있는 경우에만 메소드가 예외를 포착해야합니다.

그렇지 않으면 호출 스택을 높이는 방법이 의미가 있기를 바랍니다.

다른 사람들이 지적했듯이, 치명적인 오류가 기록되도록하려면 호출 스택의 최상위 수준에서 처리되지 않은 예외 처리기 (로깅 포함)를 사용하는 것이 좋습니다.


12
또한 try블록 생성 비용 (생성 된 코드 측면에서)이 있음을 주목할 가치가 있습니다 . Scott Meyers의 "더 효과적인 C ++"에 대한 좋은 토론이 있습니다.
Nick Meyer

28
실제로 try블록은 최신 C 컴파일러에서 무료이며 정보는 Nick입니다. 또한 지역 정보 (실제로 명령이 실패한 곳)를 잃어 버렸기 때문에 최상위 예외 처리기에 동의하지 않습니다.
Blindy

31
@Blindly : 최상위 예외 처리기는 예외를 처리하기 위해 존재하지 않지만 실제로 처리되지 않은 예외가 있음을 크게 외치고 메시지를주고 프로그램을 정상적으로 종료합니다 (호출 대신 1을 반환 terminate) . 안전 메커니즘에 가깝습니다. 또한 try/catch예외가없는 경우 거의 무료입니다. 전파하는 것이있을 때마다 던져지고 잡힐 때마다 시간이 소비되므로, try/catch그 재연 의 체인은 비용이 들지 않습니다.
Matthieu M.

17
잡히지 않는 예외로 인해 항상 충돌해야한다고 동의하지 않습니다. 최신 소프트웨어 디자인은 매우 구획화되어 있는데 왜 하나의 오류가 발생하여 나머지 응용 프로그램 (그리고 더 중요한 것은 사용자!)을 처벌해야합니까? 가장 마지막으로하고 싶은 일을 중단하면 최소한 나머지 응용 프로그램에 액세스 할 수없는 경우에도 작업을 저장할 수있는 작은 코드 창을 사용자에게 제공하십시오.
Kendall Helmstetter Gelner

21
Kendall : 예외가 최상위 핸들러에 도달하면 애플리케이션은 정의되지 않은 상태입니다. 특정한 경우에는 사용자의 데이터를 보존하는 것이 가치가 있지만 (Word의 문서 복구를 염두에두면) 프로그램은 파일을 덮어 쓰거나 데이터베이스에 커밋해서는 안됩니다.
휴 브라켓

136

으로 미치 다른 사람이 언급 한, 당신은 당신이 어떤 방법으로 처리 할 계획하지 않는 예외를 잡을 것이다. 응용 프로그램에서 디자인 할 때 예외를 체계적으로 처리하는 방법을 고려해야합니다. 이는 일반적으로 추상화를 기반으로 한 오류 처리 계층을 갖습니다. 예를 들어, 데이터 액세스 코드에서 모든 SQL 관련 오류를 처리하여 도메인 개체와 상호 작용하는 응용 프로그램의 일부가 해당 사실에 노출되지 않도록합니다. 어딘가에있는 DB입니다.

"모든 곳에서 잡기" 냄새 외에도 피하고 싶은 몇 가지 관련 코드 냄새가 있습니다 .

  1. "catch, log, rethrow" : 범위 기반 로깅을 원하는 경우 예외 (ala std::uncaught_exception()) 로 인해 스택이 언 롤링 될 때 소멸자에 로그 명령문을 생성하는 클래스를 작성하십시오 . 관심이있는 범위 내에서 로깅 인스턴스를 선언하고 로깅이 있으며 불필요한 try/ catch논리가 없어야 합니다.

  2. "캐치, 던지기 번역" : 일반적으로 추상화 문제를 나타냅니다. 몇 가지 특정 예외를 하나의 일반적인 예외로 변환하는 페더레이션 솔루션을 구현하지 않는 한 불필요한 추상화 계층이 있을 수 있습니다 . "내일 필요할 수도 있습니다"라고 말하지 마십시오 .

  3. "잡기, 청소, 다시 던지기" : 이것은 내 애완 동물 주인공 중 하나입니다. 이 항목이 많으면 Resource Acquisition is Initialization (초기화 기술) 기법을 적용 하고 정리 부분을 관리인 개체 인스턴스 의 소멸자에 배치해야 합니다.

try/ catch블록으로 흩어진 코드는 코드 검토 및 리팩토링을위한 좋은 대상으로 생각합니다. 예외 처리가 잘 이해되지 않았거나 코드가 am–ba가되어 리팩토링이 심각하게 필요함을 나타냅니다.


6
# 1은 처음입니다. +1입니다. 또한 # 2에 대한 일반적인 예외에 주목하고 싶습니다. 라이브러리를 자주 디자인하는 경우 내부 예외를 라이브러리 인터페이스에 의해 지정된 것으로 변환하여 커플 링을 줄입니다 (이것이 의미하는 것일 수도 있습니다) "연합 솔루션"으로 작성되었지만 해당 용어에 익숙하지 않습니다.
rmeador

3
기본적으로 당신이 말한 것 : parashift.com/c++-faq-lite/exceptions.html#faq-17.13
Björn Pollex

1
코드 냄새가 아니지만 의미가있는 # 2는 기존 예외를 중첩 된 예외로 유지하여 향상시킬 수 있습니다.
중복 제거기

1
# 1에 관해서 : std :: uncaught_exception ()은 비행 중에 잡히지 않은 예외가 있음을 알려 주지만 AFAIK 만 catch () 절을 사용하면 해당 예외가 실제로 무엇인지 결정할 수 있습니다. 따라서 잡히지 않은 예외로 인해 스코프를 종료한다는 사실을 기록 할 수 있지만, 포함 된 try / catch 만 사용하여 세부 사항을 기록 할 수 있습니다. 옳은?
Jeremy

@ Jeeremy-당신이 맞습니다. 일반적으로 예외를 처리 할 때 예외 세부 정보를 기록합니다. 중간 프레임의 흔적을 갖는 것이 매우 유용합니다. 일반적으로 스레드 ID 또는 식별 컨텍스트를 로그하고 로그 행을 상관시켜야합니다. 모든 로그 라인에 스레드 ID를 포함하는 Logger것과 유사한 클래스를 사용하고 log4j.Logger예외가 활성화되었을 때 소멸자에서 경고를 생성했습니다.
D.Shawley

48

다음 질문은 "예외가 있는데 다음에 무엇을해야합니까?"입니다. 무엇을 하시겠습니까? 당신이 아무것도하지 않으면-그것은 오류 숨기기이며 프로그램은 무슨 일이 있었는지 찾을 수있는 기회없이 "작동하지 않을 수 있습니다". 예외가 발생하면 정확히 무엇을하는지 이해하고 알아야 할 경우에만 파악해야합니다.


29

try-catch는 여전히 호출 스택 아래로 함수에서 발생하는 처리되지 않은 예외를 포착 할 수 있으므로 try-catches로 모든 블록 을 처리 할 필요는 없습니다 . 따라서 모든 함수에 try-catch가있는 것이 아니라 응용 프로그램의 최상위 논리에서 하나를 가질 수 있습니다. 예를 들어, SaveDocument()다른 메소드 등을 호출하는 많은 메소드를 호출하는 최상위 루틴 이있을 수 있습니다 .이 서브 메소드는 자체 시도 캐치가 필요하지 않습니다.SaveDocument() .

이는 세 가지 이유에서 유용합니다. 오류를보고 할 수있는 단일 장소가 SaveDocument()catch 블록 이라는 점에서 편리합니다 . 모든 하위 방법에 걸쳐이 작업을 반복 할 필요는 없습니다. 어쨌든 원하는 것은 바로 사용자에게 잘못된 일에 대한 유용한 진단을 제공하는 단일 장소입니다.

둘째, 예외가 발생할 때마다 저장이 취소됩니다. 모든 하위 메소드 try-catching에서 예외가 발생하면 해당 메소드의 catch 블록에 들어가 실행이 함수를 떠나고 통해 전달됩니다SaveDocument() . 무언가 잘못 되었다면 바로 멈추고 싶을 것입니다.

셋째, 모든 하위 메소드 는 모든 호출이 성공했다고 가정 할 수 있습니다 . 호출이 실패하면 실행이 catch 블록으로 이동하여 후속 코드가 실행되지 않습니다. 이렇게하면 코드를 훨씬 더 깨끗하게 만들 수 있습니다. 예를 들어, 오류 코드는 다음과 같습니다.

int ret = SaveFirstSection();

if (ret == FAILED)
{
    /* some diagnostic */
    return;
}

ret = SaveSecondSection();

if (ret == FAILED)
{
    /* some diagnostic */
    return;
}

ret = SaveThirdSection();

if (ret == FAILED)
{
    /* some diagnostic */
    return;
}

예외로 작성하는 방법은 다음과 같습니다.

// these throw if failed, caught in SaveDocument's catch
SaveFirstSection();
SaveSecondSection();
SaveThirdSection();

이제 무슨 일이 일어나고 있는지 훨씬 명확 해졌습니다.

예외 안전 코드는 다른 방법으로 작성하기가 더 까다로울 수 있습니다. 예외가 발생하면 메모리를 유출하지 않으려 고합니다. 개체는 예외 전에 항상 소멸되므로 RAII , STL 컨테이너, 스마트 포인터 및 소멸자에서 리소스를 해제하는 기타 개체 에 대해 알고 있어야 합니다.


2
훌륭한 예. 예,로드 / 저장 / 등과 같은 '트랜잭션'작업과 같은 논리 단위로 가능한 한 높게 잡습니다. 아무것도 외모 반복, 중복과 후추 코드보다 더 try- catch블록이 모든 약간 다른 그들은 모두 같은 끝나야 현실에서 약간 다른 메시지와 함께 몇 가지 오류의 순열, 최대 플래그 시도 : 거래 나 프로그램이 실패하고 종료! 예외적 인 실패가 발생하면 대부분의 사용자는 10 가지 수준의 메시지를 처리하지 않고 혼자 할 수있는 것을 구하고 싶어합니다.
underscore_d

이것이 내가 읽은 최고의 "초기 던져, 늦게 잡아"설명 중 하나라고 말하고 싶었습니다. 간결하고 예제는 여러분의 요점을 완벽하게 보여줍니다. 감사합니다!
corderazo00

27

허브 셔터는이 문제에 대해 쓴 여기 . 읽을 가치가 있습니다.
티저 :

"예외 안전 코드 작성은 기본적으로 올바른 위치에 'try'와 'catch'를 작성하는 것에 관한 것입니다." 논의하다.

솔직히 말해서, 그 진술은 예외 안전에 대한 근본적인 오해를 반영합니다. 예외는 오류보고의 또 다른 형태 일 뿐이며, 오류 안전 코드 작성은 리턴 코드를 확인하고 오류 조건을 처리 할 수있는 곳이 아니라는 것을 확실히 알고 있습니다.

실제로, 예외 안전은 'try'와 'catch'를 작성하는 것이 거의 아니며, 더 나은 경우는 거의 없습니다. 또한 예외 안전이 코드 디자인에 영향을 미친다는 것을 잊지 마십시오. 조미료처럼 ​​몇 가지 추가 catch 문으로 개조 할 수있는 것은 결코 사후 생각이 아닙니다.


15

다른 답변에서 언급했듯이 합리적인 오류 처리를 수행 할 수있는 경우에만 예외를 잡아야합니다.

예를 들어, 질문 을 생성 한 질문에서 질문자는 lexical_cast정수에서 문자열까지의 예외를 무시해도 안전한지 묻습니다 . 그러한 캐스트는 절대 실패해서는 안됩니다. 실패하면 프로그램에서 무언가 잘못되었습니다. 그런 상황에서 어떻게 회복 할 수 있습니까? 신뢰할 수없는 상태이기 때문에 프로그램을 죽이는 것이 가장 좋습니다. 따라서 예외를 처리하지 않는 것이 가장 안전한 방법 일 수 있습니다.


12

예외를 던질 수있는 메소드의 호출자에서 항상 예외를 즉시 처리하면 예외는 쓸모 없게되고 오류 코드를 사용하는 것이 좋습니다.

예외는 콜 체인의 모든 메소드에서 처리 할 필요가 없다는 것입니다.


9

제가 들었던 가장 좋은 조언은 예외적 인 조건에 대해 현명하게 무언가를 할 수있는 지점에서만 예외를 잡아야하며 "캐치, 로그 및 릴리스"가 좋은 전략이 아니라는 것입니다 (라이브러리에서 가끔 피할 수없는 경우).


2
@ KeithB : 나는 그것을 두 번째로 좋은 전략이라고 생각합니다. 다른 방법으로 로그를 작성할 수 있으면 더 좋습니다.
David Thornley

1
@KeithB : "라이브러리에있는 것보다 더 나은"전략입니다. "캐치, 로그, 올바르게 처리"가 가능하면 더 좋습니다. (예, 항상 가능하지는 않습니다.)
Donal Fellows

6

가장 낮은 수준에서 가능한 많은 예외를 처리하기 위해 귀하의 질문의 기본 방향에 동의합니다.

기존 답변 중 일부는 "예외를 처리 할 필요가 없습니다. 다른 사람이 스택에서 처리합니다." 내 경험 에 따르면 현재 개발 된 코드에서 예외 처리를 생각하지 않고 다른 사람의 문제를 예외 처리 하는 것은 나쁜 변명 입니다.

이 문제는 분산 개발에서 급격히 커져 동료가 구현 한 메서드를 호출해야 할 수 있습니다. 그런 다음 중첩 된 메소드 호출 체인을 검사하여 왜 예외가 발생했는지 파악해야합니다.이 메소드는 가장 깊은 중첩 된 메소드에서 훨씬 쉽게 처리 할 수 ​​있습니다.


5

컴퓨터 과학 교수가 한 번 알려준 조언은 "표준 수단으로는 오류를 처리 할 수없는 경우에만 Try and Catch 블록을 사용하십시오."

예를 들어, 그는 프로그램이 다음과 같은 일을 할 수없는 곳에서 심각한 문제가 발생하면 다음과 같이 말했습니다.

int f()
{
    // Do stuff

    if (condition == false)
        return -1;
    return 0;
}

int condition = f();

if (f != 0)
{
    // handle error
}

그런 다음 try, catch 블록을 사용해야합니다. 예외를 사용하여이를 처리 할 수 ​​있지만 예외는 성능이 비싸기 때문에 일반적으로 권장되지 않습니다.


7
이것이 하나의 전략이지만 많은 사람들은 예외를 사용하여 함수에서 오류 코드 또는 실패 / 성공 상태를 반환 하지 않는 것이 좋습니다 . 예외 기반 오류 처리는 종종 오류 코드 기반 코드보다 읽기 쉽습니다. (예를 들어이 질문에 대한 AshleysBrain의 답변을 참조하십시오.) 또한 많은 컴퓨터 과학 교수들은 실제 코드 작성 경험이 거의 없다는 것을 항상 기억하십시오.
Kristopher Johnson

1
-1 @Sagelika 귀하의 답변은 예외를 피하는 것으로 구성되므로 try-catch가 필요하지 않습니다.
Vicente Botet Escriba

3
@ 크리스토퍼 (Kristopher) : 리턴 코드의 또 다른 큰 단점은 리턴 코드를 확인하는 것을 잊어 버리기가 쉽다는 것입니다. 그리고 호출 직후에 문제를 처리하기에 가장 좋은 장소는 아닙니다.
David Thornley

ehh, 그것은 달려 있지만, 많은 경우 (실제로하지 않아야 할 때 던지는 사람들을 제외하고) 예외는 여러 가지 이유로 반환 코드보다 우수합니다. 에 대부분의 경우, 예외가 성능에 유해하다는 생각은 [표창장은 필요로했다] 큰 팔자 '입니다
underscore_d

3

모든 함수의 결과를 테스트하려면 리턴 코드를 사용하십시오.

예외의 목적은 결과를 자주 테스트 할 수 있도록하는 것입니다. 이 아이디어는 더 일반적인 코드에서 예외적 인 (특별하고 드문) 조건을 분리하는 것입니다. 이것은 일반적인 코드를 더 깨끗하고 단순하게 유지하지만 여전히 예외적 인 조건을 처리 할 수 ​​있습니다.

잘 설계된 코드에서는 더 깊은 함수가 발생하고 더 높은 함수가 잡힐 수 있습니다. 그러나 핵심은 "사이에있는"많은 기능이 예외적 인 조건을 처리해야하는 부담에서 벗어날 수 있다는 것입니다. 그것들은 "예외 안전"이어야만하므로 반드시 붙잡아 야한다는 의미는 아닙니다.


2

이 토론에 C ++ 11부터 모든 catch블록 rethrow이 처리 할 수 ​​있거나 처리해야 할 시점까지 예외가 발생하는 한 많은 의미가 있음을이 토론에 추가하고 싶습니다 . 이 방법 으로 역 추적을 생성 할 수 있습니다 . 따라서 이전 의견은 부분적으로 구식이라고 생각합니다.

사용 std::nested_exceptionstd::throw_with_nested

여기여기 에 StackOverflow에 설명되어 있습니다 .

파생 된 예외 클래스로이 작업을 수행 할 수 있으므로 이러한 역 추적에 많은 정보를 추가 할 수 있습니다! 역 추적이 다음과 같은 GitHub 에서 내 MWE를 살펴볼 수도 있습니다 .

Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"

2

여러 프로젝트를 구제 할 수있는 "기회"가 주어졌고 앱에 오류가 너무 많고 사용자가 문제와 해결 방법에 지 쳤기 때문에 경영진이 전체 개발 팀을 교체했습니다. 이 코드베이스는 모두 최상위 투표 답변이 설명하는 것처럼 앱 수준에서 중앙 집중식 오류 처리를했습니다. 그 대답이 최선의 방법이라면 왜 효과가 없었으며 이전 개발자 팀이 문제를 해결할 수 있었습니까? 아마도 때때로 작동하지 않습니까? 위의 답변은 개발자가 단일 문제를 해결하는 데 시간이 얼마나 걸리는지 언급하지 않습니다. 문제를 해결하는 시간이 핵심 측정 기준 인 경우 try..catch 블록을 사용하여 계측 코드를 작성하는 것이 좋습니다.

팀이 UI를 크게 변경하지 않고 어떻게 문제를 해결 했습니까? 간단하고 모든 메소드는 try..catch가 차단되어 계측되고 메소드 이름, 오류 메시지, 오류 메시지, 앱 이름, 날짜와 함께 전달 된 문자열로 연결된 메소드 매개 변수 값으로 실패 시점에 모든 것이 기록됩니다. 그리고 버전. 이 정보를 통해 개발자는 오류에 대한 분석을 실행하여 가장 많이 발생하는 예외를 식별 할 수 있습니다! 또는 오류 수가 가장 많은 네임 스페이스. 또한 모듈에서 발생하는 오류가 올바르게 처리되고 여러 가지 이유로 인한 것이 아닌지 확인할 수 있습니다.

이것의 또 다른 장점은 개발자가 오류 로깅 방법에서 하나의 중단 점을 설정하고 하나의 중단 점과 "step out"디버그 버튼을 한 번만 클릭하면 실제에 대한 전체 액세스에 실패한 방법에 있다는 것입니다. 고장 시점의 물체는 즉시 창에서 편리하게 사용할 수 있습니다. 디버깅이 매우 쉬우 며 실행을 메소드의 시작 부분으로 끌어서 문제점을 복제하여 정확한 행을 찾을 수 있습니다. 중앙 집중식 예외 처리를 통해 개발자가 30 초 내에 예외를 복제 할 수 있습니까? 아니.

"방법은 합리적인 방법으로 처리 할 수있을 때만 예외를 잡아야합니다." 이는 개발자가 출시 전에 발생할 수있는 모든 오류를 예측하거나 발생할 수 있음을 의미합니다. 이것이 최상위 수준 인 경우 앱 예외 처리기가 필요하지 않으며 Elastic Search 및 logstash에 대한 시장이 없습니다.

이 접근 방식을 통해 개발자는 프로덕션에서 간헐적 인 문제를 찾아 수정할 수 있습니다! 프로덕션 환경에서 디버거없이 디버깅 하시겠습니까? 아니면 화가 난 사용자로부터 전화를 받고 전자 메일을 받으시겠습니까? 이를 통해 다른 사람이 알기 전에 문제를 해결할 수 있으며 문제를 해결하는 데 필요한 모든 것이 있으므로 이메일, IM 또는 Slack을 지원하지 않아도됩니다. 이슈의 95 %를 재현 할 필요가 없습니다.

제대로 작동하려면 네임 스페이스 / 모듈, 클래스 이름, 메서드, 입력 및 오류 메시지를 캡처하고 데이터베이스에 저장할 수있는 중앙 집중식 로깅과 결합해야합니다. 먼저 고정.

때때로 개발자는 catch 블록에서 스택을 예외로 처리하려고하지만이 방법은 일반 코드보다 100 배 느립니다. 로깅을 통한 캐치 및 릴리스가 선호됩니다.

이 기술은 2 년 동안 12 명의 개발자가 개발 한 Fortune 500 대 기업에서 대부분의 사용자에게 1 시간마다 실패한 앱을 빠르게 안정화하는 데 사용되었습니다. 이 3000 가지 다른 예외를 사용하여 4 개월 만에 식별, 수정, 테스트 및 배포되었습니다. 평균적으로 4 개월 동안 평균 15 분마다 수정됩니다.

코드를 작성하는 데 필요한 모든 것을 입력하는 것이 재미없고 반복 코드를 보지 않는 것을 선호하지만 각 방법에 4 줄의 코드를 추가하는 것이 장기적으로 가치가 있습니다.


1
모든 블록을 감싸는 것은 지나친 것처럼 보입니다. 빠르게 코드가 부풀어지고 읽기가 어렵습니다. 더 높은 수준의 예외에서 스택 추적을 로깅하면 문제가 발생한 위치와 오류 자체와 결합 된 정보만으로도 충분한 정보를 얻을 수 있습니다. 충분하지 않은 부분이 궁금합니다. 그냥 다른 사람의 경험을 얻을 수 있습니다.
user441521

1
"예외는 일반 코드보다 100 ~ 1000 배 느리며 다시 생각해서는 안됩니다."-대부분의 최신 컴파일러와 하드웨어에서는이 문장이 사실이 아닙니다.
Mitch Wheat

과잉으로 보이며 약간의 타이핑이 필요하지만 프로덕션에서 간헐적 오류를 포함하여 가장 큰 오류를 찾아 수정하기 위해 예외에 대한 분석을 수행하는 유일한 방법입니다. catch 블록은 필요한 경우 특정 오류를 처리하고 기록하는 단일 코드 줄을 갖습니다.
user2502917

아니요, 예외는 매우 느립니다. 대안은 리턴 코드, 오브젝트 또는 변수입니다. 이 스택 오버플로 게시물을 참조하십시오 ... "예외는 반환 코드보다 30,000 배 이상 느립니다" stackoverflow.com/questions/891217/…
user2502917

1

위의 조언 외에도 개인적으로 try + catch + throw를 사용합니다. 다음과 같은 이유로 :

  1. 다른 코더의 경계에서 다른 사람이 작성한 호출자에게 예외가 발생하기 전에 나 자신이 작성한 코드에서 try + catch + throw를 사용하면 코드에서 발생한 오류 조건을 알 수 있습니다. 이 장소는 코드에 훨씬 더 가깝고 처음에는 예외를 던지고, 더 가깝고, 이유를 찾기가 더 쉽습니다.
  2. 모듈의 경계에서 다른 모듈이 같은 사람으로 작성 될 수 있습니다.
  3. 학습 + 디버그 목적,이 경우 C ++에서 catch (...)를 사용하고 C #에서 catch (Exception ex)를 사용합니다 .C ++의 경우 표준 라이브러리가 너무 많은 예외를 throw하지 않으므로이 경우는 C ++에서는 드 rare니다. 그러나 C #의 일반적인 장소 인 C #에는 거대한 라이브러리와 성숙한 예외 계층 구조가 있습니다 .C # 라이브러리 코드는 많은 예외를 던집니다. 이론 I (그리고 당신)은 호출 한 함수의 모든 예외를 알아야하며 이유 / 이유를 알아야합니다. 이러한 예외가 발생하고이를 적절하게 처리 (통과 또는 적절하게 처리 및 처리)하는 방법을 알고 있습니다. 불행히도 실제로 한 줄의 코드를 작성하기 전에 잠재적 예외에 대한 모든 것을 아는 것은 매우 어렵습니다. 따라서 예외가 발생할 때 로깅 (제품 환경에서) / 어설 션 대화 상자 (개발 환경에서)를 통해 모두를 잡아 내 코드를 크게 말하게합니다. 이런 식으로 예외 처리 코드를 점진적으로 추가합니다. 나는 그것이 좋은 조언과 충돌한다는 것을 알고 있지만 실제로 그것은 나에게 효과적 이며이 문제에 대한 더 좋은 방법을 모른다.

1

Mike Wheat의 대답이 주요 요점을 잘 요약했지만 다른 대답을 추가해야한다고 생각합니다. 나는 이것을 이렇게 생각합니다. 여러 가지 작업을 수행하는 메소드가있는 경우 추가하지 않고 복잡성을 곱합니다.

다시 말해, try catch에 싸여있는 방법에는 두 가지 가능한 결과가 있습니다. 예외가 아닌 결과와 예외 결과가 있습니다. 많은 방법을 다룰 때 이것은 이해를 넘어 기하 급수적으로 증가합니다.

기하 급수적으로 각 방법이 서로 다른 두 가지 방식으로 분기되는 경우 다른 방법을 호출 할 때마다 이전 수의 잠재적 결과가 제곱되기 때문입니다. 다섯 가지 방법을 호출 할 때 최소 256 가지의 가능한 결과를 얻을 수 있습니다. 모든 단일 방법에서 try / catch를 수행 하지 않는 것과 이것을 비교하면 하나의 경로 만 따라야합니다.

그것이 기본적으로 내가 보는 방법입니다. 응용 프로그램의 상태가 기본적으로 정의되지 않기 때문에 모든 유형의 분기가 동일한 작업을 수행하지만 try / catch는 특별한 경우라고 주장 할 수 있습니다.

간단히 말해 try / catch는 코드를 이해하기 훨씬 어렵게 만듭니다.


-2

내부 코드의 모든 부분을 다룰 필요는 없습니다 try-catch. try-catch블록 의 주요 용도는 오류 처리 및 프로그램에 버그 / 예외가있는 것입니다. 일부 사용법 try-catch-

  1. 예외를 처리하려는 위치에서이 블록을 사용하거나 작성된 코드 블록이 예외를 발생시킬 수 있다고 간단히 말할 수 있습니다.
  2. 사용 직후 객체를 폐기하려면 try-catch블록 을 사용할 수 있습니다 .

1
"개체를 사용한 직후에 폐기하려면 try-catch 블록을 사용할 수 있습니다." 이것이 RAII / 최소 객체 수명을 증진 시키려고 했습니까? 그렇다면, try/ catch는 그것과 완전히 분리 / 직교 적입니다. 더 작은 범위의 개체를 처리하려면, 당신은 단지 새로운를 열 수 없습니다 { Block likeThis; /* <- that object is destroyed here -> */ }-이 포장 할 필요 try/ catch당신이 실제로 필요하지 않는 한 catch물론, 아무것도.
underscore_d

# 2-예외에서 수동으로 생성 된 객체를 처리하는 것이 이상하게 보입니다. 이것은 의심 할 여지없이 일부 언어에서 유용 할 수 있지만 일반적으로 try / except 블록 내에서 시도 / 마지막으로 수행합니다. 특히 except 블록 자체에서-객체 자체가 처음에 예외의 원인이었을 수 있으므로 다른 예외 및 잠재적으로 충돌이 발생할 수 있습니다.
TS
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.