Как освободить malloc'd 2D массив в C? - PullRequest
0 голосов
/ 04 ноября 2019

Ниже приведен мой код, и я не могу понять, где я иду неправильно, чтобы освободить мой 2d массив. Я знаю, что ошибка происходит в этой строке: free (arr [i]);и я также знаю, что я должен сделать этот цикл, чтобы освободить каждое целое число, прежде чем освободить весь массив позже. Кто-нибудь может обнаружить ошибку здесь? Я не получаю ошибок компиляции, но после запуска моего исполняемого файла появляется огромная обратная трассировка для свободной функции.

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

int main()
{
        int h = 4;
        int w = 2;
        int i, j;

        int **arr = (int**)malloc(sizeof(int*) * h);
        arr[0] = (int*)malloc(sizeof(int) * w * h);

        for (i=1; i<h; i++)
        {
                arr[i] = arr[0] + (w*i);
        }

        int count = 0;
        for (i=0; i<h; i++)
        {
                for (j=0; j<w; j++)
                {
                        arr[i][j] = count++;
                }
        }


        for (i=0; i<h; i++)
        {
                for (j=0; j<w; j++)
                {
                        printf("Array[%d][%d] = %d ", i, j, arr[i][j]);
                }
                printf("\n");
        }

        for (i=0; i<h; i++)
        {
                free(arr[i]);
        }

        free(arr);

        /*printf("\nAfter freeing the array it becomes:\n");
        for (i=0; i<h; i++)
        {
                for (j=0; j<w; j++)
                {
                        printf("Array[%d][%d] = %d ", i, j, arr[i][j]);
                }
                printf("\n");
        }*/

}

Ответы [ 4 ]

0 голосов
/ 05 ноября 2019

Памяти, которую вы выделяете при вызове arr[0] = (int*)malloc(sizeof(int) * w * h);, достаточно для всего двумерного массива. Если вы хотите использовать этот подход, т. Е. Выделить память для 2D-массива за один вызов malloc, вы можете сделать это, приведя возвращенный указатель к указателю на массив из w элементов. Тогда вы также можете освободить память в один звонок бесплатно. Нет необходимости использовать цикл for. Смотрите код ниже.

int main()
{
    int h = 4;
    int w = 2;
    int i, j;

    int (*arr)[w] = (int(*)[w])malloc(sizeof(int)*h*w); // pointer to array of w ints

    int count = 0;
    for (i=0; i<h; i++) {
        for (j=0; j<w; j++) {
            arr[i][j] = count++;
        }
    }

    for (i=0; i<h; i++) {
        for (j=0; j<w; j++) {
            printf("Array[%d][%d] = %d ", i, j, arr[i][j]);
        }
        printf("\n");
    }

    free(arr);  //<-- free the 2D array in a single free
    return 0;
}
0 голосов
/ 04 ноября 2019
//for (i=0; i<h; i++) { free(arr[i]); }//error
free(arr[0]);  //true

free(arr);
0 голосов
/ 04 ноября 2019

Когда вы используете ваши malloc, вы выделяете только первую позицию массива

arr[0] = (int*)malloc(sizeof(int) * w * h);

Это означает, что когда вам нужно освободить память, вам нужно вызвать free(arr[0]) изатем free(arr)

Это не даст вам ошибки.

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

int **arr = (int**)malloc(sizeof(int*) * h);

for (int i = 1; i < h ; ++i){
     arr[i] = (int*)malloc(sizeof(int) * w); // with the correct size you want
}    

Это позволит выделить h указателей в массиве для использования, затем вы можете освободить память, как вы делали в своем примере

РЕДАКТИРОВАТЬ: Обратите внимание, что, как @AndrewHenle правильно указал в своем комментарии, это решение не выделяет true 2D массив, а просто массив указателей на массивы. Чтобы узнать, как правильно разместить 2D-массив, см. этот связанный вопрос

0 голосов
/ 04 ноября 2019

вы выделяете память только для arr[0] = (int*)malloc(sizeof(int) * w * h);, но при освобождении выделенного пространства вы освобождаете до h count, for (i=0; i<h; i++){free(arr[i]);}. Вы должны были распределить и этот путь, используя тот же цикл.

...