Освобождение многомерных массивов в C - PullRequest
3 голосов
/ 22 декабря 2011

Допустим, у нас есть:

void createMultiArray(){
    int i,j;
    char*** codes = malloc(5 * sizeof(char**));
    for ( i = 0; i <= 4; i++ ) {
        codes[i] = malloc((i+1) * sizeof(char*));
        for ( j = 0; j <= i; j++ ) {
            codes[i][j] = malloc(2 * sizeof(char));
        }
   }

Как мне освободить codes?

free(codes);

или

int i,j;
for(i = 0; i <=4; i++){
    for(j = 0; j <= i; j++){
        free(codes[i][j]);
    }
    free(codes[i]);
}
free(codes);

Ответы [ 6 ]

6 голосов
/ 22 декабря 2011

Подумайте об этом так: у вас должно быть free для каждого malloc.

// you're allocating memory for codes
// must be freed with free(codes);
char*** codes = malloc(5 * sizeof(char**));

for ( i = 0; i <= 4; i++ ) {

    // allocating memory for every element in codes
    // must be freed with free(codes[i]);
    codes[i] = malloc((i+1) * sizeof(char*));

    for ( j = 0; j <= i; j++ ) {

        // allocating memory for every element in every element in codes
        // must be freed with free(codes[i][j])
        codes[i][j] = malloc(2 * sizeof(char));

    }
}

Так что да, ваш второй вариант правильный.

3 голосов
/ 22 декабря 2011

Вторая верна, а первая утечка памяти.Как правило, вам нужно звонить free() за каждый malloc() звонок.

3 голосов
/ 22 декабря 2011

Второй - то, что вы хотите, free не может и не будет работать рекурсивно. Каждый раз, когда вы делаете malloc, подумайте о месте, куда вы собираетесь позвонить free.

В качестве примечания: не освобождайте память, если вы в следующий раз выйдете из программы - это бессмысленно и может занять довольно много времени.

1 голос
/ 22 декабря 2011

Структура памяти для createMultiArray() будет выглядеть следующим образом:

            codes[i]       codes[i][j]
***         **             *      
+-+         +-+            +-+-+
|0|-------->| |----------->| | | 
+-+         +-+            +-+-+
|1|-----+                   | | 
+-+     |   +-+             | | 
|2|     +-->| |             | +------------- char
+-+         +-+             +--------------- char
|3|         | + 
+-+         +-+ 
|4| 
+-+         ....            ....

Теперь вернитесь и освободите каждую память, которую вы создали, используя free [да, для каждого malloc() должно быть free()]

OTOH, ты уверен, что хочешь это сделать?

for ( i = 0; i <= 4; i++ ) {
    codes[i] = malloc((i+1) * sizeof(char*));
    ....
}

for i=0, malloc will create 1 memory cell
for i=1, malloc will create 2 memory cell
for i=2, malloc will create 3 memory cell
for i=3, malloc will create 4 memory cell
for i=4, malloc will create 5 memory cell

Это намеренно?

1 голос
/ 22 декабря 2011

Желательно, чтобы вы не использовали вложенные malloc () - s, если вы можете заранее рассчитать размер массива. Вы должны распределить и освободить за один шаг (сделать вашу жизнь проще и уменьшить вероятность ошибок).

0 голосов
/ 22 декабря 2011

Не используйте такие сложные схемы размещения для эмуляции многомерных массивов.В частности, в вашем случае, когда все границы являются константами времени компиляции.

char (*codes)[n][m] = malloc(sizeof(char[x][n][m]));

выполняет ту же цель и требует только одного

free(codes);

в конце.Если контекст, в котором вы используете этот массив, даже привязан к одной области видимости, а ваши границы невелики, вы можете даже выделить его непосредственно как переменную auto и даже инициализировать его одновременно

char codes[23][2][5] = { { { 'a', 'b'}  } };

.бесплатно в конце.

...