Использование free () на указателях двумерного массива с несколькими malloc ()? - PullRequest
0 голосов
/ 15 ноября 2018

У меня есть функция, которая выделяет двумерный массив внутри функции, возвращая указатель на массив. Для создания массива требуется массив указателей, каждый из которых содержит адрес строки двумерного массива.

Как правильно освободить эти два malloc() вызова вне этой функции после завершения работы с этим массивом?

int** allocateMatrix(int rows, int cols)
{
    int* arr = malloc(rows*cols*sizeof(int));
    int** matrix = malloc(rows*sizeof(int*));
    int i;
    for(i=0; i<rows; i++)
    {
        matrix[i] = &(arr[i*cols]);
    }
    return matrix;
 }

Функция используется так:

int** 2d_arr = allocateMatrix(row,cols);

Спасибо!

Ответы [ 3 ]

0 голосов
/ 15 ноября 2018

Это будет работать:

void freeMatrix( int **matrix )
{
    free( matrix[ 0 ] );
    free( matrix );
}

Потому что для i == 0 этот код

matrix[i] = &(arr[i*cols]);

устанавливает matrix[ 0 ] на адрес arr[0], который является тем же значением, которое возвращается после первого malloc вызова:

int* arr = malloc(rows*cols*sizeof(int));

Будет понятнее, если вы напишите матричное распределение, например

int** allocateMatrix(int rows, int cols)
{
    int** matrix = malloc(rows*sizeof(int*));
    matrix[ 0 ] = malloc(rows*cols*sizeof(int));

    int i;
    for(i=1; i<rows; i++)
    {
            matrix[i] = &(arr[i*cols]);
    }
    return matrix;
 }

Обратите внимание на изменение порядка malloc(), прямое присвоение matrix[ 0 ] и изменение индекса цикла, начиная с 1.

0 голосов
/ 15 ноября 2018

Я предлагаю вам использовать один malloc() для выделения всей области памяти, чтобы упростить управление как один указатель.

Я считаю, что следующая измененная версия вашей функции должна работать.

int** allocateMatrix(int rows, int cols)
{
    size_t  sMemSize = rows*sizeof(int*) + rows*cols*sizeof(int);
    int** matrix = malloc(sMemSize);
    int* arr = (int *) (matrix + rows);
    int i;
    for(i=0; i<rows; i++)
    {
        matrix[i] = &(arr[i*cols]);
    }
    return matrix;
 }

Тогда вы можете просто сделать free(2d_arr);, где int** 2d_arr = allocateMatrix (nRows, nCols);.

0 голосов
/ 15 ноября 2018

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

Первая строка 2d_arr, т.е. 2d_arr[0], содержит &arr[0*cols] == &arr[0] == arr. Итак, вы хотите освободить это и matrix себя:

free(2d_arr[0]);
free(2d_arr);
...