main ()에서 return 문과 exit ()


197

내가 사용해야 exit()하거나 return의 문 main()? 개인적으로 return코드를 읽을 때 다른 기능을 읽고 흐름 제어를 읽는 것과 같은 느낌이 들기 때문에 진술을 선호합니다 (제 의견으로는). 그리고 main()함수 를 리팩토링하고 싶더라도 return보다 더 나은 선택처럼 보입니다 exit().

않습니다 exit()아무것도 특별 할 return하지 않습니다?

답변:


277

사실, 거기에 있다 차이,하지만 미묘한입니다. C ++에는 더 많은 의미가 있지만 차이점이 중요합니다.

내가 전화를 할 경우 returnmain(), 소멸자는 내 로컬 범위 객체에 대해 호출됩니다. 내가 호출 할 경우 exit(), 더 소멸자 내 로컬 범위 객체에 대해 호출되지 않습니다! 다시 읽어보세요. exit() 반환하지 않습니다 . 즉, 일단 전화를 걸면 "백시가 없습니다"라는 의미입니다. 해당 함수에서 생성 한 객체는 파괴되지 않습니다. 이것은 종종 영향을 미치지 않지만 때로는 파일을 닫는 것과 같이 영향을 미칩니다 (모든 데이터를 디스크로 플러시 하시겠습니까?).

참고 것을 static당신이 호출하면 객체도 정리됩니다 exit(). 마지막으로를 사용 abort()하면 객체가 파괴되지 않습니다. 즉, 전역 객체, 정적 객체 및 로컬 객체가 없어도 소멸자가 호출됩니다.

복귀 초과 이탈을 선호 할 때는주의하여 진행하십시오.

http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a


1
abort ()는 오류 조건 (제로가 아닌 종료 코드)으로 종료되며 핵심 일 수도 있습니다. 정적 소멸자를 호출하지 않고 종료 해야하는 경우 _exit를 사용하십시오.

7
@ Mike : C 라이브러리 파일 버퍼와 C ++ 파일 스트림 개체간에 차이가 있습니다. exit ()-C 라이브러리의 일부-전자를 조정하고 플러시하도록 설계되었지만 후자를 우회 할 수 있습니다. 표준 C ++ fstream 컨텐츠조차도 디스크로 플러시되지 않습니다 (시도했습니다-Linux / w에 실패했습니다) GCC), 그리고 분명히 I / O를 버퍼링 한 사용자 정의 형식은 플러시 할 수 없습니다.
Tony Delroy

9
참고 : 성명 : 로컬 범위가 지정된 객체에는 소멸자가 호출되지 않습니다! C ++ 11의 경우 더 이상 적용되지 않습니다.-스레드 스토리지 기간이있는 현재 스레드와 연관된 오브젝트가 삭제됩니다 (C ++ 11 전용). cplusplus.com/reference/cstdlib/exit
Ilendir

7
즉, thread_local객체의 소멸자가 호출됩니다. 다른 로컬 객체의 소멸자는 여전히 호출되지 않습니다. ideone.com/Y6Dh3f
HolyBlackCat

3
BTW, 그리고 단지 pedantic 하고이 답변은 C를 사용하는 독자에게는 여전히 혼란 스러울 수 있기 때문에 : C의 경우 exit()파일을 깨끗하게 닫는 문제 는 실제로 잘못되었습니다. 즉, 하나 개를 사용하면 : 유일한 시간 데이터는 반대의 경우에 저장되지 않을 수 return에서 main()하나를 호출 한 setbuf()또는 setvbuf()버퍼가 자동 스토리지로 선언으로 main()(아래 R.의 대답에 설명 된대로). 이 질문에는 C와 C ++ 태그가 있고 태그 스타일이 아닙니다!
Greg A. Woods

25

또 다른 차이점 exit은 표준 라이브러리 기능이므로 헤더를 포함하고 표준 라이브러리와 연결해야합니다. (C ++로) 설명하기 위해 이것은 유효한 프로그램입니다.

int main() { return 0; }

그러나 사용하려면 exit다음이 포함되어야합니다.

#include <stdlib.h>
int main() { exit(EXIT_SUCCESS); }

게다가이 추가 가정을 추가 호출하는 것을 exit에서하는 main제로를 반환과 같은 부작용이있다. 다른 사람들이 지적했듯이, 이것은 어떤 종류의 실행 파일 (즉, 누가 호출하고 있는지)에 달려 main있습니다. C 런타임을 사용하는 앱을 코딩하고 있습니까? Maya 플러그인? Windows 서비스? 운전자? 각 사례 exit는에 해당 하는지 조사해야 합니다 return. IMHO 는 실제로 의미가exit 있을 때 사용하여 코드를 더 혼란스럽게 만듭니다. OTOH, 정말로 의미 한다면 , 그것을 사용하십시오. return exit


16

이 선호하는 적어도 하나의 이유는 exit당신의 경우 atexit처리기에 자동 저장 - 기간 데이터를 참조 main하거나 사용하는 경우 setvbuf또는 setbuf표준 중 하나에 할당 자동 저장-기간에 버퍼 스트림 main다음에서 돌아, main생산 정의되지 않은 동작이지만 호출 exit은 유효합니다.

또 다른 잠재적 인 사용법 (일반적으로 장난감 프로그램 용으로 예약 됨)은 재귀 적 호출이있는 프로그램을 종료하는 것입니다 main.


1
@Seb 특별한 점은 없습니다 main(). 다른 것과 마찬가지로 기능입니다. 반면에 표준에 특별히 언급되어 있기 때문에 표준은 표준을 정의 main()하고 표준과 그 주변에있는 것들 에 대해 매우 신중해야 합니다. 그러나 결국 표준은 컴파일러가 자동 저장에 대해 특별한 작업을 수행하도록 요구 하지는 않지만 ( 그렇게 해서는 안됨 ) main(). 의견에서 언급 한 단락 아래 각주 # 11 을 읽으 십시오.
Greg A. Woods

1
@ GregA.Woods 재미있는. 유익한 텍스트와 모순되는 규범적인 텍스트가있는 것 같습니다. ISO / IEC 지침 에 따르면 , 규범 적 참조는 "필수적"인 것으로 간주되며, 정보는 보충적인 것으로 간주되므로 ... 요구 사항을 전달하기 위해 "의지"라는 단어의 사용은 유효하지 않습니다. 상기 문헌 (부속서 H)에 따라. 요약하면, 유익한 텍스트는 가장 확실하지 않습니다.
자폐증

2
@Seb : 의도는 자동 저장 장치의 동작에 대한 요구 사항을 무시하는 것이 아니라는 것을 분명히하기 위해 각주가 작성되었습니다. 그렇습니다. C 표준에는 부정확하고 나쁜 표현이 있습니다. 그것을 읽은 사람은 이것을 알고 있습니다. 또한 의도가 이미 명백하기 때문에위원회는 일반적으로 이와 같은 문제를 해결하지 못한다는 것을 알고 있습니다.
R .. GitHub STOP HELPING ICE

1
@Seb : 이것은 당신이 옳다는 것을 증명하는 토론이나 법정 사건이 아닙니다. 목표 실제 C 언어 (의도 된대로)가 무엇인지 명확하게 이해하고 독자에게 유용한 답변으로 표현해야합니다. 규범적인 텍스트는 본질적으로 각주에 의해 고정 된 방식으로 미묘하게 잘못되었습니다 (표현하려는 의도와는 반대). 이것에 만족하지 않으면 결함 보고서를 제출하되 회신을 기대하지 마십시오. 그것이 WG14가 어떻게 굴러 가는가 ...
R .. GitHub 중지 지원 얼음 얼음

3
@Seb : 당신은 C 언어가 표준의 자연어 텍스트를 완전히 엄격한 것처럼 해석함으로써 이해할 수 있다고 생각합니다. 이것은 단순히 불가능합니다. 이 사양에는 실수가 포함되어 있으며 WG14는 간단한 각주에서 실수를했다는 것을 이미 알고 있지만 독자가 이해할 수 있음을 명확하게 설명 할 때 시간을 낭비하지 않습니다.
R .. GitHub 중지 도움말 얼음

5

return대한 표준 프로토 타입에서을 main()반환한다고해서 항상 사용 합니다 int.

즉, 일부 표준 버전은 main특별한 처리 방법을 제공하며 명시적인 return진술 이 없으면 0을 반환한다고 가정합니다 . 다음 코드가 주어진다 :

int foo() {}
int main(int argc, char *argv[]) {}

G ++는 다음에 대한 경고 만 생성 foo()하고 누락 된 리턴을 무시합니다 main.

% g++ -Wall -c foo.cc
foo.cc: In function int foo()’:
foo.cc:1: warning: control reaches end of non-void function

C에 대해서는 잘 모르지만 C ++ 표준은 main에서 값을 반환하지 않으면 0을 반환한다고 가정합니다.
Jason Baker

C99와 같은 것 같습니다 : faq.cprogramming.com/cgi-bin/…
Jason Baker

2
C99와 C ++는 return 문이 없으면 0을 반환하고 C90은 0을 반환하지 않습니다.
d0k

함수가 반환 값을 갖는 것으로 선언되었다고해서 return실행을 끝내기 위해 사용해야한다는 의미는 아닙니다 . 호출 exit()은 또한 모든 함수의 실행을 종료하는 유효하고 때로는 필요한 방법입니다. 실제로 나와 다른 사람들이 다른 곳에서 설명했듯이 전화를 걸 exit()더라도 main()전체 프로세스를 종료하려는 의도가 훨씬 명확 해지고 프로세스가 종료 될 때까지 자동 저장이 유지되며 향후 코드 리팩토링 동안 유지 관리가 더 쉬워집니다. 의도를 끝내기 위해 C를 사용 return하는 main()경우 프로세스가 나쁜 습관 일 것입니다.
Greg A. Woods

@ GregA.Woods는 귀하의 의견이지만, 투표권은 거의 없습니다! 위에서 쓴 것은 standard와 완전히 일치하는 반면, 당신의 주장은 의미 론적입니다.
Alnitak

5

나는 강력히 에서 자동 스토리지 것을 방지하기 위해 exit ()를 사용하는 방법에 대한 R.에 의해 두 번째 주석 main()프로그램이 실제로 끝나기 전에 재생을. return X;in 의 명령문은 main()에 대한 호출과 정확하게 동일 하지 않습니다. 리턴 할 때 exit(X);동적 스토리지의 동적 저장이 main()사라지 main()지만 exit()대신 호출 이 이루어지면 사라지지 않습니다 .

또한 C 또는 C와 같은 언어에서는 return명령문이 독자에게 실행이 호출 함수에서 계속 될 것이라고 강력히 암시하며,이 실행 계속은 일반적으로 main()함수 를 호출 한 C 시작 루틴을 계산하면 기술적으로 사실이지만 그렇지 않습니다. 정확히 무엇을 당신은 당신이 프로세스를 종료하는 것을 의미 할 때 의미한다.

당신이 다른 함수 내에서 프로그램을 종료 할 경우 결국 제외하고 main()합니다 전화 exit(). 일관되게 그렇게하면 main()코드를보다 읽기 쉽게 만들 수 있으며 누구나 코드를 쉽게 리팩터링 할 수 있습니다. 즉, main()다른 함수로 복사 된 코드 는 호출 되어야 하는 우연한 return진술 로 인해 오작동하지 않습니다 .exit()

따라서 이러한 모든 사항을 결합하면 결론적으로 적어도 C 는 프로그램을 끝내기 위해 명령문을 사용하는 것이 나쁜 습관 이라는 것 return입니다 main().


당신은 찾을 수 는 C 표준의 5.1.2.2.3p1 ... 재미를
자폐증

이 답변은 문맥에 따라 C 프로그램에 대해 신중하게 고려할 가치가 있습니다. C ++과 함께 사용하려면 앞에서 언급 한 모든 경고에 대해 신중하게 평가해야합니다. C ++의 경우 exit()일반적 으로 피하는 것이 좋지만 특정 컨텍스트에서 a throw또는 abort()대안이 작동하지 않으면 사용하십시오 . 그러나 특히 exit()main에서는 피하고 일반적인 방법으로 main에서 return을 사용하십시오.
Eljay

5

exit ()는 'return'이 아닌 특별한 작업을 수행합니까?

흔하지 않은 플랫폼을위한 일부 컴파일러를 사용하면 exit()인수를 프로그램의 종료 값으로 변환 할 수 있지만 반환 main()값은 변환없이 호스트 환경으로 직접 값을 전달할 수 있습니다.

이 경우 표준은 동일한 동작을 요구합니다 (특히, int호환되는 것을 반환하는 것은 해당 값 main()으로 호출 exit()하는 것과 동일해야 함 ). 문제는 OS마다 종료 값을 해석하기위한 규칙이 다르다는 것입니다. 많은 (MANY!) 시스템에서 0은 성공을 의미하고 다른 것은 실패입니다. 그러나 VMS의 경우 홀수 값은 성공을 의미하고 하나는 실패를 의미합니다. 에서 0을 반환 main()하면 VMS 사용자에게 액세스 위반에 대한 불쾌한 메시지가 표시됩니다. 실제로 액세스 위반은 없었습니다. 이는 단순히 실패 코드 0과 관련된 표준 메시지였습니다.

그리고 ANSI가 함께 와서 축복 EXIT_SUCCESSEXIT_FAILURE인수로 당신에게 전달할 수 있습니다 exit(). 이 표준은 또한 exit(0)동일하게 동작해야 exit(EXIT_SUCCESS)하므로 대부분의 구현은에 정의 EXIT_SUCCESS되어 0있습니다.

따라서 표준 은 값이 0 인 오류 코드 를 리턴하는 표준 방법을 남기지 않으므로 VMS에 바인드합니다 .

따라서 1990 년대 초 VAX / VMS C 컴파일러는의 반환 값을 해석하지 않고 main()단순히 호스트 환경에 값을 반환했습니다. 그러나 사용 exit()했다면 표준에서 요구하는 작업을 수행 할 수 있습니다 . 성공 코드 및 일반 실패 코드로 변환 EXIT_SUCCESS(또는 0) EXIT_FAILURE합니다. 사용하려면 EXIT_SUCCESS, 당신은 했다 그것을 통과 exit(), 당신은에서를 반환 할 수 없었다 main(). 그 컴파일러의 최신 버전이 그 동작을 유지했는지 여부는 모르겠습니다.

휴대용 C 프로그램은 다음과 같습니다.

#include <stdio.h>
#include <stdlib.h>

int main() {
  printf("Hello, World!\n");
  exit(EXIT_SUCCESS);  /* to get good return value to OS */
  /*NOTREACHED*/ /* to silence lint warning */
  return 0;  /* to silence compiler warning */
}

따로 : 내가 정확하게 기억한다면, 종료 값에 대한 VMS 규칙은 홀수 / 짝수보다 더 미묘합니다. 실제로 심각도 레벨을 인코딩하기 위해 낮은 3 비트와 같은 것을 사용합니다. 그러나 일반적으로 홀수 심각도 수준은 성공 또는 기타 정보를 나타내며 짝수 레벨은 오류를 나타냅니다.


일부 이전 pre-ANSI 컴파일러는 전달 된 값과 다르게 값 returned을 처리했을 수도 있지만 표준에서는 " 함수 의 반환 유형이 와 호환되는 유형 인 경우 초기 호출에서 반환 된 함수는 다음과 같습니다. 함수가 인수로 반환 한 값을 사용 하여 함수 를 호출하는 것과 같습니다 . " C11입니다. C89 / C90은 거의 같은 표현을 가지고있었습니다. mainexitmainintmainexitmain
키이스 톰슨

과연. 그럼에도 불구하고 일부 ANSI 시대 컴파일러는 이러한 권리를 얻지 못했으며 호스트 환경으로 반환되는 올바른 반환 값을 얻기 위해 명시 적으로 exit를 사용해야했습니다. 표준 (그런데도)은 0과 동일하게 취급해야하므로 EXIT_SUCCESS플랫폼 특정 실패 상태를 값 0 으로 리턴 할 방법이 없었기 때문에 ,이 시대의 일부 컴파일러가 메인에서 리턴 처리 그리고 exit()다르게.
Adrian McCarthy

이에 대한 인용이 있습니까? 별도의 문제는 현재 컴파일러에 특정 버그 가 있는지 여부 입니다. 귀하의 답변은 현재 시제로 표시됩니다.
키이스 톰슨

그것은 공정한 비판입니다. 내가 아는 특정 사례로 범위를 제한하기 위해 문구를 변경했습니다.
Adrian McCarthy

0

C에서 리턴하는 main것은 exit동일한 값 으로 호출하는 것과 정확히 동일합니다.

C 표준 상태의 5.1.2.2.3 절 :

main 함수의 리턴 유형이 int와 호환되는 유형 인 경우, 초기 함수에서 main 함수로의 리턴은 main 함수가 리턴 한 값을 인수로 사용하여 exit 함수를 호출하는 것과 같습니다 . 11) main 함수를 종료하는}에 도달하면 값 0이 리턴됩니다. 리턴 유형이 int와 호환되지 않으면 호스트 환경으로 리턴 된 종료 상태는 지정되지 않습니다.

C ++의 규칙은 다른 답변에서 언급했듯이 약간 다릅니다.


-1

실제로 사이에 차이가 exit(0)return(0)에가 main- 귀하의 경우 main함수가 여러 번 호출됩니다.

다음 프로그램

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
  if (argc == 0)
    return(0);
  printf("%d", main(argc - 1, argv));
}

다음으로 실행

./program 0 0 0 0

다음과 같은 결과가 나타납니다.

00000

그러나 이것은 :

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
  if (argc == 0)
    exit(0);
  printf("%d", main(argc - 1, argv));
}

인수에 관계없이 아무 것도 인쇄하지 않습니다.

아무도 main명시 적으로 전화하지 않을 것이라고 확신한다면 기술적으로 큰 차이는 아니지만 명확한 코드를 유지하는 exit것이 훨씬 좋습니다. 어떤 이유로 든 전화를 원한다면 main필요에 따라 조정해야합니다.

C에 대해 말하기

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.