2011-07-05 1 views
0

C 프로그램을 디버깅하는 중입니다. 3 차원의 거대한 데이터 배열이 필요합니다. 메모리 할당/해제를위한 두 가지 기능을 개발했습니다.동적 메모리 할당에 대한 내 C 코드의 문제점/다차원 배열에 대한 무료

mm()은 각 차원의 크기를 기록하는 배열을 참조하여 할당을 위해 설계되었습니다 (main()에서 볼 수 있음). ff()은 메모리를 해제하는 데 사용됩니다.

fr() 실행 후 top 명령으로 코드를 테스트했습니다. 그것은 메모리가 해제되지 않은 것을 보여줍니다. 누구든지 그걸 밝힐 수 있습니까?

미리 감사드립니다.

PID USER  PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 
28338 fsdiag 25 0 165m 164m 1208 R 63.2 26.0 0:00.33 a.out 
3439 root  15 0 31740 1180 21m S 1.9 0.2 10:56.47 X 


int main(){ 

unsigned char ***arr; 
int dim_len[4]={8832,256,64,0}; // for 3-D array, 0 is mark of tail 
unsigned char *p; 

mm(&p, dim_len, 0); arr = (unsigned char ***)p; 
ff((unsigned char **)&arr, dim_len); 

while(1){} 
return 0; 
} 

void mm( unsigned char **a, 
      int dim_len[], //dimension size array guarded by 0 in the tail 
      unsigned char data){ //preset data 
    if(*dim_len){ 
     int i; 
     switch(*(dim_len+1)){ 
      case 0://when allocate memory for unsigned char 
       *a = malloc(sizeof(unsigned char) * (*dim_len)); 
       break; 
      default://when allocate memory for pointers 
       *a = malloc(sizeof(unsigned char *) * (*dim_len)); 
       for(i=0; i<(*dim_len); i++){ 
        mm((unsigned char **)&((*a)[i*4]), dim_len+1, data); 
       } 
       break; 
     }//end of switch 
    }//end of if 
    return; 
} 


void ff( unsigned char **a, 
      int dim_len[]){//dimension size array guarded by 0 in the tail 
    if(*dim_len){ 
     int i; 
     switch(*(dim_len+1)){ 
      case 0://when free memory for unsigned char 
       free(*a); 
       break; 
      default://when free memory for pointers 
       for(i=0; i<(*dim_len); i++){ 
        ff((unsigned char **)&((*a)[i*4]), dim_len+1); //pointer needs 4 bytes storage 
       } 
      free(*a); 
       break; 
     }//end of switch 
    }//end of if 
    *a = NULL; 
    return; 
} 
+1

위에 더 많은 메모리를 사용할 보여 않습니다, 다음은 바로 해방 후 ps 직전 의 출력은? 아주 자주,'free'는 해제 된 메모리를 사용할 수 있다고 표시합니다. OS로 반환하지 않습니다. – pmg

+0

이 예제 코드의 배열 크기는 컴파일 타임에 알려 지므로 'typedef unsigned char twoD [256] [64]; twoD * p = malloc (8832 * sizeof (* p));'. 하지만 실제 코드에서는 그렇지 않을 수도 있습니다. –

답변

3

당신은 dim_len의 숫자 제품의 크기와 메모리의 한 덩어리를 malloc을해야한다.

할당 된 데이터가 조각화되어 있어야하고 그 이상이어야하며 코드에 어떤 이점이있는 시나리오를 상상해보십시오. 대신 인덱스를 arithmetics을하는, 익숙한 p[i][j][k] 표기법 요소를 액세스 할 수 있기 때문에 배열의 배열의 배열과 다차원 배열을 정의

+0

확실히. 연속적인 메모리 블록 하나만 있으면 stride로 액세스 할 수 있습니다. 'element (i, j, k) = buf [i + DIM1 * j + DIM2 * k]; –

+0

적절한 다차원 배열 대신에 포인터 배열을 사용하는 "이점"은 다차원 배열처럼 보이는 구문에 액세스한다는 것입니다. 즉, arr [DIM1 * DIM2] 대신 [arr [i] [j] [k] * i + DIM2 * j + k]'로 표시됩니다. –

+0

아, 또 다른 가능한 * 이점은 메모리가 조각화되는 것입니다.이 경우 DIM1 * DIM2가 사용 가능한 가장 인접한 주소 범위보다 작 으면 DIM1 * DIM2 * DIM3이 사용 가능한 최대 연속 길이보다 큽니다 주소 범위가 있다면, 이전 메모리가 더 많은 메모리를 필요로하더라도, 단편화 된 메모리는 단 하나의 블록에 할당하는 것이 가능할 수도 있습니다. 이 경우, 144MB는 PC에서의 합리적인 단일 할당이며, 잠재적 인 위험 일지라도 과도한 것으로 보입니다. –

0

, 매우 편리 입니다. 그러나 다른 사람 이미 큰 덩어리로 전체 배열을 할당하는 것보다 효율적이지 않습니다 지적했다.

당신은 다음과 같은 트릭 두 세계의 최고를 가질 수 dim_len[0]*dim_len[1]*dim_len[2] 데이터 셀의 배열에 dim_len[0]*dim_len[1] 포인터의 배열에 에게 dim_len[0] 포인터의 배열을 할당합니다. 은 포인터의 배열 중간 배열이 제대로 초기화 되었다면, 쉽게 p[i][j][k] 표기법을 사용할 수 있습니다. 이렇게 세 가지 할당 (차원만큼)이 가능합니다. 원하는 경우 **p에 색인을 입력 할 수도 있습니다. 여기

/* 
* Allocation of multidimensional arrays. 
*/ 

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

/* 
* Allocate a multidimensional array of unsigned chars. 
* Cast the returned pointer to (unsigned char **...*) 
*/ 
void *mm(const int dim_len[]) 
{ 
    int i, j, size, nmemb = 1, prev_nmemb; 
    void *p = NULL, *q = NULL; 
    void **prev_q; 

    for (i = 0; dim_len[i]; i++) { 
     prev_nmemb = nmemb; 
     nmemb *= dim_len[i]; 
     size = dim_len[i+1] ? sizeof(void *) : sizeof(unsigned char); 
     prev_q = q; 
     q = malloc(nmemb * size); 
     if (i == 0) p = q; 
     else for (j = 0; j < prev_nmemb; j++) 
      prev_q[j] = q + j * dim_len[i] * size; 
    } 
    return p; 
} 


/* Free the multidimensional array */ 
void ff(void *p, int dimensions) 
{ 
    int i; 
    void **q; 

    for (i = 0; i < dimensions; i++) { 
     q = *((void **) p); 
     free(p); 
     p = q; 
    } 
} 

int main(void) 
{ 
    const int dims[4] = {8832, 256, 64, 0}; 
    unsigned char ***p; 
    int i, j, k; 

    printf("Allocating memory.\n"); 
    p = mm(dims); 
    printf("Filling the array.\n"); 
    for (i = 0; i < dims[0]; i++) 
     for (j = 0; j < dims[1]; j++) 
      for (k = 0; k < dims[2]; k++) 
       p[i][j][k] = (i + 3*j + 5*k) % 256; 
    printf("Checking contents.\n"); 
    for (i = 0; i < dims[0]; i++) 
     for (j = 0; j < dims[1]; j++) 
      for (k = 0; k < dims[2]; k++) 
       assert(p[i][j][k] == (i + 3*j + 5*k) % 256); 
    printf("Waiting 10 seconds.\n"); 
    sleep(10); 
    printf("Freeing memory.\n"); 
    ff(p, 3); 
    printf("Waiting 10 seconds.\n"); 
    sleep(10); 
    return 0; 
} 

내 테스트 내가 다차원 배열을 해제 할 때, 메모리 실제로 OS에 반환되는 것을 보여

여기에 그 트릭을 사용하여 프로그램의 내 버전입니다. 당신이 그것을 해제 한 후 메모리를 재사용하는 경우

USER  PID %CPU %MEM VSZ RSS TTY  STAT START TIME COMMAND 
edgar  5201 73.0 3.7 151852 150556 pts/0 S+ 14:11 0:00 ./test 
edgar  5201 6.1 0.0 1668 408 pts/0 S+ 14:11 0:00 ./test 
관련 문제