2011-07-05 28 views
0

我正在調試C程序。需要一個包含三維數據的龐大數據數組。我爲內存分配/免費開發了兩個函數。我的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

如果你重用已經釋放之後的內存,並狀元秀使用更多內存?很多時候,'free'只是將釋放的內存標記爲可用;它不會將其返回到操作系統。 – pmg

+0

請注意,由於本示例代碼中的數組維數在編譯時已知,因此您可以執行'typedef unsigned char twoD [256] [64]; twoD * p = malloc(8832 * sizeof(* p));'。但是在你真實的代碼中可能不是這種情況。 –

回答

3

您應該malloc只有一塊內存與dim_len中的數字乘積的大小。

您分配的數據比較分散並且比它應該大,我很難想象任何您的代碼都有什麼好處的場景。

+0

當然。只需一個連續的內存塊,你可以用步長訪問它,元素(i,j,k)= buf [i + DIM1 * j + DIM2 * k];'。 –

+0

使用指針數組代替適當的多維數組的好處是,訪問它們的語法看起來像一個多維數組:arr [i] [j] [k]'而不是'arr [DIM1 * DIM2 * i + DIM2 * j + k]'。 –

+0

噢,另外一個可能的*內存碎片優勢可能不是在這種情況下,如果DIM1 * DIM2小於最大可用連續地址範圍,並且DIM1 * DIM2 * DIM3大於最大可用連續地址範圍,那麼儘管前者需要更多的內存總量,但可能會分配內存碎片,但不能在單個塊中分配內存。在這種情況下,144MB在個人電腦上是合理的單一分配,無論如何分割到64B似乎都是過分的,即使這是潛在的風險。 –

0

定義多維數組的數組的數組的數組是 非常方便,因爲你可以用熟悉的 p[i][j][k]符號訪問的,而不是做指數算術的元素。然而,其他 已經指出,它比整個陣列作爲一個大塊分配效率低。

你可以有最好的與下面的技巧兩個世界:分配 的dim_len[0]指針數組的dim_len[0]*dim_len[1] 指針數組dim_len[0]*dim_len[1]*dim_len[2]數據單元陣列。 這樣你只有三個分配(與維數一樣多),並且你的 仍然可以使用簡單的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; 
} 

我在這裏的測試表明,當我釋放多維數組,內存 實際上是返回到操作系統。這裏是ps之前和 剛剛釋放後的輸出:

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