중단, 종료 또는 종료 하시겠습니까?


112

이 세 가지의 차이점은 무엇이며 제대로 처리 할 수없는 예외가 발생하면 프로그램을 종료하려면 어떻게해야합니까?


3
이것은 중복이 아니라 좋은 답변이있는 하위 집합입니다. stackoverflow.com/questions/397075/… 그리고 C ++ 태그도 붙였습니다!
Ellie Kesselman 2012 년

std::abort소멸자에서 예외를 해결할 수없는 경우 타당합니다.
Daniel

1
자세한 내용 std::terminate은 Andrzej의 뛰어난 C ++ 블로그에서 다음 기사를 참조하십시오. akrzemi1.wordpress.com/2011/09/28/who-calls-stdterminate , akrzemi1.wordpress.com/2011/10/05/using-stdterminate
Ohad Schneider

답변:


3

내 조언은 그것들을 사용하지 않는 것입니다. 대신 catch처리 할 수없는 예외 main()return거기에서 간단하게 . 이것은 스택 해제가 올바르게 발생하고 모든 소멸자가 호출된다는 것을 보장합니다. 다시 말해:

int main() {
    try {
       // your stuff
    }
    catch( ... ) {
       return 1;    // or whatever
    }
}

8
@Neil : 기본적으로 동의하지만 프로그램이 처리 할 수없는 예외는보고하고 다시 던져야합니다. 앱 충돌을 허용합니다.
John Dibling

13
스택이 풀리도록하려면 항상 메인을 잡아야합니다. 그러나 나는 캐치에서 다시 던질 것입니다. 일부 OS에는 디버그에서 컴파일 한 경우 디버깅 인프라를 자동으로 호출하는 기능이 있습니다.
Martin York

5
최상위 수준 처리기로도 포착되지 않은 예외는 프로세스를 덤프하고 Windows 오류보고, Mac OS X 오류 보고서 및 iPhone 애플리케이션 오류 로그와 같은 개발자의주의를 위해 예외 보고서를 업로드하는 시스템보고 기능을 호출 할 수 있습니다.
JBRWilkinson

6
@John 저에게 놀라운 이유는 예외가 실제로 구현되는 방식에 비추어 완벽하게 이해할 수 있지만 적절한 핸들러가 발견 될 때까지 예외가 "스택 위로 전파"한다는 추상화를 깨뜨리기 때문입니다 (또는 종료는 전화). 그리고 누출 된 추상화는 피할 수없는 경우가 많지만 만났을 때 반드시 놀라운 일입니다.
Tyler McHenry

11
-1 이것은 질문의 절반에 대한 답이 아니기 때문입니다. "[중단, 종료 또는 종료]의 차이점은 무엇입니까?"이것이 더 나은 대답입니다. stackoverflow.com/a/397081/353094 또한 stackoverflow.com/a/2820407/353094 도 훌륭한 대답입니다.
leetNightshade

149
  • abort 는 프로그램에 대한 "비정상적인"종료를 나타내고 POSIX 신호 SIGABRT를 발생시킵니다. 즉, 해당 신호에 대해 등록한 모든 핸들러가 호출되지만 프로그램은 두 경우 모두 종료됩니다. 일반적으로 abortC 프로그램에서 오류가 잘못된 입력이나 네트워크 실패와 같은 것이 아니라 프로그램의 버그 일 가능성이있는 예기치 않은 오류 사례에서 종료하는 데 사용합니다. 예를 들어, abort논리적으로 절대 발생하지 않아야하는 데이터 구조에 NULL 포인터가있는 것이 발견되면 가능합니다.

  • 종료 는 프로그램의 "정상적인"종료를 나타내지 만 여전히 오류 (버그는 아님)를 나타낼 수 있습니다. 즉, exit사용자가 구문 분석 할 수없는 입력을 제공했거나 파일을 읽을 수없는 경우 오류 코드가 표시 될 수 있습니다. 종료 코드 0은 성공을 나타냅니다. exit또한 프로그램을 종료하기 전에 선택적으로 핸들러를 호출합니다. 이들은 atexiton_exit기능 으로 등록됩니다 .

  • std :: terminate 는 처리되지 않은 예외가있을 때 C ++ 프로그램에서 자동으로 호출되는 것입니다. abort예외를 throw하여 모든 예외적 인 오류를보고한다고 가정하면 기본적으로 C ++에 해당합니다 . 이것은 std::set_terminate기본적으로 단순히 호출 하는 함수에 의해 설정된 핸들러를 호출합니다 abort.

C ++에서는 일반적으로 호출 abort또는 exit오류 발생 을 피하고 싶을 것입니다 . 예외를 던지고 코드가 호출 스택에서 프로그램을 종료하는 것이 적절한 지 여부를 결정하도록하는 것이 더 낫기 때문입니다. exit성공 을 위해 사용 하는지 여부는 상황의 문제입니다. .NET의 return 문이 아닌 다른 곳에서 프로그램을 종료하는 것이 타당한 지 여부입니다 main.

std::terminateC ++에서도 최후의 오류보고 도구로 간주되어야합니다. 문제는 std::terminate않습니다 핸들러를 종료한다는 것입니다 하지 처리되지 않은 갔다 예외에 액세스 할 수 있으므로이 무엇인지 알 수있는 방법은 없습니다. 일반적으로 메인 전체를 try { } catch (std::exception& ex) { }블록으로 감싸는 것이 훨씬 낫습니다 . 최소한 다음에서 파생 된 예외에 대한 자세한 정보를보고 할 수 있습니다 std::exception(물론 파생되지 않은 예외 std::exception는 여전히 처리되지 않은 상태가됩니다).

mainin 의 본문을 래핑하는 try { } catch(...) { }것은 종료 처리기를 설정하는 것보다별로 좋지 않습니다. 왜냐하면 다시 해당 예외에 대한 액세스 권한이 없기 때문입니다. 편집 : Neil Butterworth의 대답에 따르면이 경우 스택이 풀리는 이점이 있습니다. 이는 처리되지 않은 예외에 대해서는 사실이 아닙니다.


10
이 답변을 C ++ 11 정보로 업데이트 할 수 있습니까? 이제 catch (...) 및 종료 처리기에서 예외를 얻는 방법이있는 것 같습니다.
Klaim

1
C ++에서 종료 핸들러는 수행 을 통해 예외에 액세스 할 수 있습니다 std::current_exception(). 여기에서 예를보십시오 : akrzemi1.wordpress.com/2011/10/05/using-stdterminate
anorm

검사 할 수 없기 때문에 현재 예외를 얻을 수 있다는 것은 중요하지 않습니다. 당신이 할 수있는 것은 그것을 다시 던지는 것입니다.
seattlecpp

2
@seattlecpp 당신은 그것을 다시 던지고 그것에 대한 참조를 잡을 수 있습니다. 그런 다음 그것을 조사 할 수 있습니다
gpeche

16

std :: abort 및 std :: exit (및 기타 : std :: _ Exit, std :: quick_exit)는 저수준 함수입니다. 호출 할 소멸자 (및 경우), 호출 할 다른 정리 함수, 반환 할 값 등 정확히 원하는 작업을 프로그램에 알리기 위해 사용합니다.

std :: terminate는 더 높은 수준의 추상화입니다. (런타임 또는 사용자에 의해) 호출되어 프로그램에서 오류가 발생했으며 어떤 이유로 예외를 throw하여 처리 할 수 ​​없음을 나타냅니다. 그 필요성은 일반적으로 예외 메커니즘 자체에서 오류가 발생할 때 발생하지만 프로그램이 주어진 오류 이상으로 계속되는 것을 원하지 않을 때 언제든지 사용할 수 있습니다. 내 게시물에서 std :: terminate가 호출 될 때 상황의 전체 목록을 컴파일 했습니다.. std :: terminate가 수행하는 작업은 사용자가 제어하기 때문에 지정되지 않습니다. 기능을 등록하여 동작을 구성 할 수 있습니다. 제한 사항은 함수가 오류 사이트로 돌아갈 수없고 예외를 통해 종료 할 수 없다는 것입니다. 그러나 기술적으로는 내부에서 메시지 펌프를 시작할 수도 있습니다. 내부에서 할 수있는 유용한 작업 목록은 다른 게시물을 참조하세요 .

특히 std :: terminate는 처리 할 수없는 throw 된 예외로 인해 std :: terminate가 호출되는 컨텍스트에서 예외 처리기로 간주되며 예외가 무엇인지 확인하고 C ++를 사용하여 검사 할 수 있습니다. 11 std :: rethrow_exception 및 std :: current_exception 사용. 그것은 모두 내 게시물에 있습니다.


시스템 신호로 인해 프로그램이 종료되는 경우 정리 처리기를 사용하는 것이 좋습니까? 예를 들어 유효하지 않은 메모리 액세스는 SIGSEGV 신호를 생성합니다. 이 경우 프로그램을 종료하고 코어 파일을 갖도록하거나 정리를 수행 할 신호 처리기를 등록하는 것이 좋습니까 ?? std :: terminate를 처리하는 동안 정리를 수행하는 것과 비교하여 시스템 신호를 처리하는 동안 정리를 수행하는 것에 대한 우려가 있습니까?
kartik trivikram

12

quick_exit () !

프로그램이 다중 스레드 인 경우 exit()전역 / 정적 std::thread개체가 스레드를 종료하지 않고 소멸을 시도하기 때문에 호출 하면 충돌이 발생할 가능성이 큽니다 .

오류 코드를 반환하고 프로그램을 정상적으로 종료하려면 (다소) quick_exit()다중 스레드 프로그램을 호출하십시오 . 비정상 종료 (오류 코드 지정 가능성 없음) abort()또는 std::terminate()호출 할 수 있습니다.

참고 : quick_exit ()는 2015 버전까지 MSVC ++에서 지원되지 않았습니다 .


4
  • 종료하면 호출 될 때 일어날 일을 등록 할 수 있습니다. 다른 두 개 중 하나 여야합니다.
  • exit는 종료 상태를 지정할 수있는 일반 종료입니다. at_exit ()에 의해 등록 된 핸들러가 실행됩니다.
  • abort는 비정상적인 종료입니다. 실행되는 유일한 것은 SIGABRT에 대한 신호 처리기입니다.

4
  • 처리 할 수없는 예외가 발생하면 종료 ()가 자동으로 호출됩니다. 기본적으로 terminate ()는 abort ()를 호출합니다. set_terminate () 함수로 사용자 정의 핸들을 설정할 수 있습니다.

    abort ()는 SIGABRT 신호를 보냅니다.

    exit ()가 반드시 나쁜 것은 아닙니다. 응용 프로그램을 성공적으로 종료하고 LIFO 순서로 atexit () 함수를 호출합니다. 나는 일반적으로 C ++ 응용 프로그램에서 이것을 보지 못하지만, 끝에 종료 코드를 보내는 많은 유닉스 기반 응용 프로그램에서 볼 수 있습니다. 일반적으로 exit (0)은 응용 프로그램이 성공적으로 실행되었음을 나타냅니다.


8
실패! Unix와 DOS에서 exit (0)은 성공을 나타내고 exit ()에 전달 된 다른 값은 실패를 나타내며 그 반대는 아닙니다!
Richard Barrell
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.