2014-07-24 8 views
5

C에서 프로젝트를 개발 중이고 할당 된 메모리를 확보하고 종료하기 전에 열려있는 모든 파일을 닫아야합니다.전역 변수를 사용하지 않고 atexit 또는 유사하게 메모리를 비울 수있는 방법이 있습니까?

가능한 모든 종료 시나리오가 있기 때문에이 모든 작업을 수행하고 atexit이라고 부르는 clean 함수를 구현하기로 결정했습니다.

문제는 atexit에서 매개 변수가있는 함수를 설정할 수 없기 때문에 처리가 끝날 때 해제해야하는 포인터를 clean (으)로 보낼 수 없습니다.

그래서 전역 변수로 해제해야 할 수도있는 모든 포인터와 프로그램에 열려있는 모든 파일을 선언해야합니다. (나는 이미 그것을했으나 좋지 않습니다) 또는 매개 변수를 보낼 수있는 atexit과 유사한 기능이 있습니까? 아니면 내가 놓친 다른 방법이 있을까요?

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

void atexit_clean(void *data); 

static void clean(void) 
{ 
    atexit_clean(NULL); 
} 

void atexit_clean(void *data) 
{ 
    static void *x; 

    if (data) { 
     x = data; 
     atexit(clean); 
    } else { 
     free(x); 
    } 
} 

int main(void) 
{ 
    int *a = malloc(sizeof(int)); 

    atexit_clean(a); 
    return 0; 
} 

단일 글로벌 변수를 사용하는 또 다른 방법은 : 함수 내에서 정적 포인터를 사용

+1

메모리 풀을 가리키는 변수가 하나만 있으면됩니다. 그건 받아 들일 만해. – this

+2

최신 소비자 운영 체제를 사용 중이라면 종료 할 때 모든 리소스가 해제됩니다. 즉, 할당 된 메모리가 모두 해제되고 열려있는 모든 파일이 닫힙니다. –

+1

또한 예 : 파일을 전체 프로세스 런타임 중에 열어야 할 필요가 있다면 여러 위치에서 액세스 할 수도 있습니다. 즉, 이미 전역 변수이거나 적어도 하나의 번역 단위에있는 전역을 의미합니다. 그런 다음 닫을 수있는 함수를 가질 수 있습니다 그 파일은 전역'clean_all' 함수에서 호출됩니다. 할당하는 메모리와 동일합니다. –

답변

4

는 포인터의 어레이 또는 링크 된리스트에서 해제 될 모든 오브젝트를 저장할 수 있으며,이 예 realloc 사용 (atexit()에 매개 변수를 전달하는 방법이 없습니다

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

static void **vclean; 
static size_t nclean; 

void atexit_add(void *data) 
{ 
    vclean = realloc(vclean, sizeof(void *) * (nclean + 1)); 
    vclean[nclean++] = data; 
} 

void clean(void) 
{ 
    size_t i; 

    for (i = 0; i < nclean; i++) { 
     free(vclean[i]); 
    } 
    free(vclean); 
} 

int main(void) 
{ 
    int *a, *b, *c; 
    double *d; 
    int e = 1; 

    atexit(clean); 
    a = &e; 
    b = malloc(sizeof(int)); 
    atexit_add(b); 
    c = malloc(sizeof(int)); 
    atexit_add(c); 
    d = malloc(sizeof(double)); 
    atexit_add(d); 
    return 0; 
} 
+0

'atexit (clean_all);'을'main()'함수의 시작으로 옮겨야합니다. 현실적인 예를 들어'atexit_add()'를 호출하는 사이에 프로그램을 종료시키는 연산이있을 수있다. – kay

+0

@Kay, 그것은 당신이 깨끗한 방법으로 떠날 것인지 아니면 중단 할 것인지에 달려 있지만, 일반적으로 당신은 편집이 옳다. –

+0

'atexit_add()'는'realloc()'실패를 검사하고 오류 표시를 호출자에게 리턴해야합니다. –

3

전역 변수를 사용하여 부착하고, 그래서 : 간결 (m/재) ALLOC를) 확인하지 않습니다.

프로그램이 정상적으로 종료되면 exit()을 통해 또는 main()에서 복귀하여 열려있는 모든 스트림과 (대부분의 운영 체제에서) 할당 된 메모리를 자동으로 플러시하고 닫습니다. 그러나 프로그램이 종료되기 전에 명시 적으로 정리하는 것이 일반적으로 더 구조화 된 프로그램으로 연결되기 때문에 명시 적으로 정리하는 것이 좋습니다. 간혹 프로그램을 작성하는 가장 깨끗한 방법은 구현을 끝내고 정리를 종료하는 것입니다.

그러나 항상의 반환 값 fclose()을 확인해야합니다. 귀하가하지 않을 때 발생할 수있는 일화에 대해서는 "What are the reasons to check for error on close()?"을보십시오.

+1

C 표준은 할당 된 메모리를 구현할 필요가 없다는 것에주의하십시오. 사실, TI-89 시리즈의 공통적 인 문제는 종료 전에 정리하지 않는 C 프로그램과 OS가 정리하지 않았기 때문에 누출 된 프로그램을 반복적으로 실행하면 계산기의 RAM이 소모됩니다. –