source

C에서 exit()를 사용해야 합니까?

factcode 2022. 8. 14. 11:56
반응형

C에서 exit()를 사용해야 합니까?

사용법에 대한 질문이 있습니다.exitC++로 표시됩니다.답변은 주로 RAII 때문에 좋은 생각이 아니라고 주장한다. 예를 들어 다음과 같다.exit는 코드의 어딘가에서 호출되며 오브젝트의 소멸자는 호출되지 않습니다.따라서 예를 들어 파괴자가 파일에 데이터를 쓰도록 의도된 경우 파괴자가 호출되지 않았기 때문에 이러한 현상이 발생하지 않습니다.

저는 C의 상황이 어떤지 궁금했습니다.C에서도 같은 문제가 적용됩니까?C에서는 컨스트럭터/파괴자를 사용하지 않기 때문에 C에서는 상황이 다를 수 있다고 생각했습니다.그럼 사용해도 될까요?exit예를 들어 다음과 같은 기능이 C에서 사용되는 것을 본 적이 있습니다.

void die(const char *message)
{
    if(errno) {
        perror(message);
    } else {
        printf("ERROR: %s\n", message);
    }

    exit(1);
}

보다는abort(),그exit()C의 함수는 "Graceful" 출구로 간주됩니다.

C11(N1570) 7.22.4.4/p2 종료 기능(강조 지뢰):

exit함수로 인해 정상적인 프로그램 종료가 발생합니다.

또한 이 기준서는 7.22.4/p4에서 다음과 같이 기술하고 있다.

다음으로 버퍼링되지 않은 데이터를 가진 모든 열린 스트림이 플래시되고 모든 열린 스트림이 닫히고 에 의해 생성된 모든 파일이tmpfile기능이 삭제됩니다.

또, 7.21.3/p5 파일도 참조할 필요가 있습니다.

이 경우,main이 함수는 원래 발신자에게 돌아가거나exit함수가 호출되고 열려 있는 모든 파일이 닫힙니다(모든 출력 스트림이 플러시됨).프로그램 종료에 대한 기타 경로(예:abort모든 파일을 올바르게 닫을 필요는 없습니다.

단, 아래 코멘트에 기재되어 있는 것처럼 다른 모든 자원을 커버한다고는 생각할 수 없기 때문에 다음 방법을 사용해야 할 수도 있습니다.atexit()각 릴리스의 콜백을 개별적으로 정의합니다.사실 그게 바로atexit()는, 7.22.4.2/p2 에 나타나 있듯이, 다음의 기능을 실시합니다.

atexit함수는 에 의해 지적된 함수를 등록한다.func일반 프로그램 종료 시 인수 없이 호출됩니다.

특히, C 표준에서는 할당된 스토리지 기간의 객체에 대해 어떤 일이 일어나야 하는지를 정확하게 기술하고 있지 않습니다(즉,malloc()) 。따라서 특정 실장에서의 처리방법을 알고 있어야 합니다.최신 호스트 지향 OS에서는 시스템이 처리할 가능성이 높지만 Valgrind 등의 메모리 디버거를 무음화하기 위해 직접 이 문제를 해결해야 할 수도 있습니다.

네, 사용해도 괜찮습니다.exit주식회사.

모든 버퍼와 정상적인 셧다운을 보증하기 위해 이 기능을 사용하는 것이 좋습니다.atexit자세한 내용은 이쪽

코드 예는 다음과 같습니다.

void cleanup(void){
   /* example of closing file pointer and free up memory */
   if (fp) fclose(fp);
   if (ptr) free(ptr);
}

int main(int argc, char **argv){
   /* ... */
   atexit(cleanup);
   /* ... */
   return 0;
}

자, 언제든지exit이 함수는cleanup정상적으로 셧다운, 버퍼 청소, 메모리 등을 저장할 수 있습니다.

생성자와 소멸자는 없지만 리소스(파일, 스트림, 소켓 등)가 있을 수 있으므로 올바르게 닫는 것이 중요합니다.버퍼를 동기화할 수 없기 때문에 먼저 리소스를 올바르게 닫지 않고 프로그램을 종료하면 손상될 수 있습니다.

사용.exit()괜찮아요

아직 언급되지 않은 코드 설계의 두 가지 주요 측면은 '스레딩'과 '라이브러리'입니다.

싱글 스레드 프로그램에서는, 그 프로그램을 실장하기 위해서 쓰는 코드에,exit()괜찮아요.제 프로그램은 뭔가 잘못되어 코드가 복구되지 않을 때 일상적으로 사용합니다.

그런데...

단, 콜링exit()돌이킬 수 없는 일방적인 행동입니다.그래서 '스레딩'과 '라이브러리' 둘 다 신중한 생각을 필요로 한다.

스레드화된 프로그램

프로그램이 멀티 스레드인 경우exit()모든 스레드를 끝내는 극적인 액션입니다.전체 프로그램을 종료하는 것은 부적절할 수 있습니다.스레드를 종료하고 오류를 보고하는 것이 적절할 수 있습니다.프로그램 설계를 알고 있다면 일방적인 종료는 허용되지만 일반적으로는 허용되지 않습니다.

라이브러리 코드

그리고 그 '프로그램 설계 인지' 조항은 도서관의 코드에도 적용된다.범용 라이브러리 함수가 호출하는 것은 매우 드문 일입니다.exit()표준 C 라이브러리 함수 중 하나가 오류 때문에 반환되지 않았다면 당연히 화가 났을 것입니다. (분명히, 함수는 다음과 같습니다.)exit(),_Exit(),quick_exit(),abort()다시 돌아오지 않으려는 의도입니다.그것은 다릅니다.)따라서 C 라이브러리의 함수는 "실패할 수 없다"거나 오류 표시를 반환합니다.범용 라이브러리에 들어가기 위해 코드를 작성하는 경우 코드에 대한 오류 처리 전략을 신중하게 고려해야 합니다.사용하는 프로그램의 에러 처리 전략에 적합해야 합니다.그렇지 않으면 에러 처리를 설정할 수 있습니다.

일련의 라이브러리 기능이 있다(헤더가 있는 패키지에 포함)."stderr.h"(살얼음 위를 밟는 이름)은 오류 보고에 사용되므로 종료됩니다.이러한 기능은 설계상 종료됩니다.오류를 보고하고 종료하지 않는 일련의 함수가 같은 패키지에 포함되어 있습니다.물론 기존 함수는 종료되지 않는 함수로 구현되지만, 이는 내부 구현 세부 사항입니다.

나는 다른 많은 도서관 기능을 가지고 있고, 그들 중 상당수는 에 의존합니다."stderr.h"에러 리포트용 코드.그것은 제가 결정한 디자인이며, 저는 괜찮습니다.그러나 종료된 함수와 함께 오류가 보고되면 라이브러리 코드의 일반적인 유용성이 제한됩니다.코드가 종료되지 않은 오류 보고 함수를 호출할 경우 함수 내의 주요 코드 경로는 오류 반환을 적절하게 처리해야 합니다.이러 반환을 검출하여 오류 표시를 호출 코드에 릴레이합니다.


오류 보고 패키지의 코드는 GitHub의 SOQ(Stack Overflow Questions) 저장소에서 파일로 사용할 수 있습니다.stderr.c그리고.stderr.hsrc/libsoq 서브디렉토리에 있습니다.

실행하는 작업에 따라서는 종료가 C의 프로그램에서 가장 논리적인 방법일 수 있습니다.콜백 체인이 제대로 작동하는지 확인하는 데 매우 유용하다는 것을 알고 있습니다.최근에 사용한 콜백의 예를 다음에 나타냅니다.

unsigned char cbShowDataThenExit( unsigned char *data, unsigned short dataSz,unsigned char status)
{

    printf("cbShowDataThenExit with status %X (dataSz %d)\n", status, dataSz);
    printf("status:%d\n",status);
    printArray(data,dataSz);
    cleanUp();
    exit(0);
}

메인 루프에서 이 시스템의 모든 것을 설정하고 잠시 후 루프에서 대기합니다.대신 while loop을 종료하는 글로벌플래그를 만들 수 있지만 이는 간단하며 필요한 작업을 수행합니다.파일이나 디바이스등의 오픈 버퍼를 취급하고 있는 경우는, 일관성을 유지하기 위해서, 닫기 전에 버퍼를 청소할 필요가 있습니다.

피해야 할 이유 중 하나exit이외의 기능에서는main()코드가 컨텍스트에서 제외될 수 있습니다.exit은 비로컬 제어 흐름의 일종입니다.잡을 수 없는 예외처럼요

예를 들어 심각한 디스크 오류로 인해 종료되는 일부 스토리지 관리 기능을 쓸 수 있습니다.그리고 나서 누군가가 그들을 도서관으로 옮기기로 결심한다.라이브러리에서 종료하면, 콜 프로그램이 준비되지 않은 부주의한 상태로 종료됩니다.

또는 임베디드 시스템에서 실행할 수도 있습니다.나갈 곳도 없고, 모든 게 순식간에 흘러가요.while(1)루프 인하다main()표준 라이브러리에서 정의되지 않을 수도 있습니다.

대규모 프로젝트에서는 코어 덤프를 제외하고 어떤 코드도 종료할 수 있는 것은 매우 어려운 일입니다.트레이스는 온라인 서버를 유지하기 위해 매우 중요합니다.

언급URL : https://stackoverflow.com/questions/31501142/should-we-use-exit-in-c

반응형