Tim Weissenfels
Tim Weissenfels

Reputation: 29

Using free() on pointers of two dimensional array with multiple malloc()?

I have a function that allocates a two dimensional array within a function returning a pointer to the array. Creating the array requires an array of pointers each of which contains the address of a row of the two dimensional array.

How do I correctly free these two malloc() calls outside of this function once I am done with this array?

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;
 }

The function is used like this:

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

Thanks!

Upvotes: 2

Views: 121

Answers (3)

Richard Chambers
Richard Chambers

Reputation: 17593

I suggest that you use a single malloc() to allocate the entire memory area so as to make it easier to manage as a single pointer.

I believe the following modified version of your function should work.

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;
 }

Then you can just do free(2d_arr); where int** 2d_arr = allocateMatrix (nRows, nCols);.

Upvotes: 0

dbush
dbush

Reputation: 223992

You can only pass to free what was received from malloc. So the number of calls to free must be the same as the number of calls to malloc.

The first row of 2d_arr, i.e. 2d_arr[0], contains &arr[0*cols] == &arr[0] == arr. So you want to free that and matrix itself:

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

Upvotes: 4

Andrew Henle
Andrew Henle

Reputation: 1

This will work:

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

Because, for i == 0, this code

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

sets matrix[ 0 ] to the address of arr[0], which is the same value returned from the first malloc call:

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

It's clearer if you write matrix allocation like

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;
 }

Note the change in malloc() order, the direct assignment to matrix[ 0 ], and the change in loop index to start at 1.

Upvotes: 0

Related Questions