programing

종료 시 파일 설명자를 닫는 것이 좋은 방법입니까?

stoneblock 2023. 10. 31. 20:26

종료 시 파일 설명자를 닫는 것이 좋은 방법입니까?

어떤 이유에서인지 프로그램에서 치명적인 상황이 발견되어 오류 코드를 가지고 종료하고 싶습니다.치명적인 오류의 맥락이 다른 파일 설명자의 범위를 벗어나는 경우도 있습니다.파일 설명자를 닫는 것이 좋은 방법입니까?이 파일들은 프로세스가 종료되면 자동으로 닫히는 것으로 알고 있습니다.

POSIX 프로그래밍의 고전적인 가이드 "유닉스 환경에서의 고급 프로그래밍"은 다음과 같이 기술합니다.

프로세스가 종료되면 열린 모든 파일이 커널에 의해 자동으로 닫힙니다.많은 프로그램이 이 사실을 이용하고 열려 있는 파일을 명시적으로 닫지 않습니다.

질문에 OS를 언급하지 않았지만, 이러한 동작은 어느 OS에서나 예상할 수 있는 것입니다.프로그램 컨트롤 흐름이 교차할 때마다exit()아니면return부터main()공정 후 청소는 시스템 책임입니다.

OS 구현에는 항상 버그의 위험이 존재합니다.그러나 시스템은 프로세스 종료 시 여러 개의 열린 파일 디스크립터보다 훨씬 더 많은 것을 할당 해제해야 합니다. 즉 프로세스와 관련된 실행 파일 이미지, 스택, 커널 객체가 차지하는 메모리입니다.사용자 공간에서는 이 동작을 제어할 수 없으며, 사용자 공간이 의도한 대로 작동하는 것에 의존할 뿐입니다.그렇다면 프로그래머는 왜 자동으로 닫히는 것에 의존할 수 없는 것일까요?fds?

그래서, 떠나는 유일한 문제는fdsopen은 프로그래밍 스타일 질문일 수 있습니다.그리고, 을 사용하는 경우와 마찬가지로stdio개체(즉, 시스템에서 제공한 파일 i/o를 중심으로 작성된 것), valgrinding 중에 방향을 바꿀 수 없는 경고가 (somewhat) 나타날 수 있습니다.시스템 리소스 유출의 위험에 대해서는 OS 구현에 버그가 없는 한 걱정할 필요가 없습니다.

파일은 자동으로 닫히지만 좋은 방법입니다.

이 예제의 valgrind 참조

david@debian:~$ cat demo.c
#include <stdio.h>

int main(void)
{
    FILE *f;

    f = fopen("demo.c", "r");
    return 0;
}
david@debian:~$ valgrind ./demo
==3959== Memcheck, a memory error detector
==3959== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==3959== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==3959== Command: ./demo
==3959== 
==3959== 
==3959== HEAP SUMMARY:
==3959==     in use at exit: 568 bytes in 1 blocks
==3959==   total heap usage: 1 allocs, 0 frees, 568 bytes allocated
==3959== 
==3959== LEAK SUMMARY:
==3959==    definitely lost: 0 bytes in 0 blocks
==3959==    indirectly lost: 0 bytes in 0 blocks
==3959==      possibly lost: 0 bytes in 0 blocks
==3959==    still reachable: 568 bytes in 1 blocks
==3959==         suppressed: 0 bytes in 0 blocks
==3959== Rerun with --leak-check=full to see details of leaked memory
==3959== 
==3959== For counts of detected and suppressed errors, rerun with: -v
==3959== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)

보시는 것처럼 메모리 유출을 유발합니다.

어떤 상황에서는 당신이 사용할 수 있습니다.atexit():

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

static FILE *f;

static void free_all(void)
{
    fclose(f);
}

static int check(void)
{
    return 0;
}

int main(void)
{
    atexit(free_all);
    f = fopen("demo.c", "r");
    if (!check()) exit(EXIT_FAILURE);
    /* more code */
    return 0;
}

이 파일들은 프로세스가 종료되면 자동으로 닫히는 것으로 알고 있습니다.

그것에 의지하지 마세요.개념적으로 프로세스가 종료되면 할당된 메모리를 자유롭게 사용하거나 비표준 파일 설명자를 닫는 것 등이 사용자의 책임입니다.물론 프로세스가 끝나면 모든 정상적인 OS(그리고 Windows(윈도우))가 정리되지만, 이는 기대할 수 있는 것이 아닙니다.

예. 메인 프로그램이 이제 다른 프로그램의 클래스라고 가정해 보겠습니다.지금 당신은 자원 유출에 대해 설명했습니다.전역 프로그램 상태, 즉 프로세스의 상태(모듈, 클래스, ADT, 스레드, 전체 프로세스)에 의존하여 본질적으로 캡슐화를 위반하는 것입니다.

프로그램이 종료되면 모든 정상 운영 체제(확실히 어떤 형태의 Linux 또는 Windows)가 파일을 닫습니다.아주 간단한 프로그램이 있다면 종료 시 파일을 닫을 필요가 없을 것입니다.그러나 파일을 명시적으로 닫는 것은 다음과 같은 이유로 여전히 좋은 방법입니다.

  1. OS에 맡기면 파일이 닫히는 순서를 제어할 수 없기 때문에 일관성 문제(예: 다중 파일 데이터베이스)가 발생할 수 있습니다.

  2. 파일 닫기와 관련된 오류(예: I/O 오류, 공간 부족 오류 등)가 있는 경우 해당 오류를 보고할 방법이 없습니다.

  3. 처리해야 하는 파일 잠금과 상호 작용이 있을 수 있습니다.

  4. 모든 파일을 닫는 루틴은 프로그램에 필요한 다른 정리를 동시에 처리할 수 있습니다(예: flushing 버퍼).

C는 프로그램이 정상적으로 종료될 경우 열려 있는 모든 파일이 닫힐 것을 보장합니다.exit혹은 로부터의 답례main프로그램이 비정상적으로 종료되는 경우(예: NULL 포인터 사용으로 인해 운영 체제에서 닫히는 경우) 파일을 닫는 것은 운영 체제의 몫입니다.따라서 예기치 않게 종료될 경우 파일이 더 이상 필요하지 않게 되면 파일이 닫히도록 하는 것이 좋습니다.

또 다른 이유는 자원 제한 때문입니다.대부분의 운영 체제는 열려 있는 파일 수에 제한을 두고 있으며(다른 여러 가지 파일도 포함), 따라서 리소스가 더 이상 필요하지 않은 경우 즉시 반환하는 것이 좋습니다.모든 프로그램이 모든 파일을 무한정 열어두었다면 시스템에 문제가 빨리 발생할 수 있습니다.

언급URL : https://stackoverflow.com/questions/15246833/is-it-a-good-practice-to-close-file-descriptors-on-exit