1
votes

How to free a two dimensional array using a function allocated memory using int ** ptr?

For example I use allocArray( &ptrArray, row, column); to allocate the array. What is the proper procedure to free the allocated memory using this function: void freeArray( int *** pA, int row, int column)

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

void allocArray( int *** pA, int row, int column)
{
    int i, j, count;

    *pA = (int **) malloc(row * sizeof(int *));
    for (int i =0; i<row; ++i)
    {
        (*pA)[i] = (int *) malloc( column * sizeof(int));
    }
    // Note that pA[i][j] is same as *(*(pA+i)+j)
    count = 0;
    for (i = 0; i <  row ; i++)
        for (j = 0; j < column; j++)
            (*pA)[i][j] = ++count;  // OR *(*(pA+i)+j) = ++count

    for (i = 0; i <  row; i++)  {
        for (j = 0; j < column; j++)  {
            printf("%d ", (*pA)[i][j]);
        }
        printf("\n");
    }
}

// How to free a two dimensional array  allocated memory using int ** ptr?
void freeArray( int *** pA, int row, int column)
{

}

void test_array_allocation()
{
    int i, j;
    int row = 3, column = 4;
    int ** ptrArray;

    allocArray( &ptrArray, row, column);

    printf("test_array_allocation\n");
    for (i = 0; i <  row; i++)  {
        for (j = 0; j < column; j++)  {
            printf("%d ", (ptrArray)[i][j]);
        }
        printf("\n");
    }
    freeArray(&ptrArray, row, column); // free allocated memory  
}

int main(int argc, const char * argv[]) {
    test_array_allocation();  
    return 0;
}
3
Essentially the same thing, but in reverse order: first, free every (*pA)[i], then free *pA. You might want to redesign your code though. It is rarely a good sign when things like int *** start showing up. - Filipe Gonçalves
If you were doing it, can you show me how you would do this? - Brian
much better to use a function prototype of : 'void * allocArray( int nodeLength, int numRow, int numCol ) the inside the function: void * theArray = NULL; then allocate the row pointers and clear them all to NULL. then, allocate each row of columns. It would be better is the initialization of the row columns be initialized separately rather that as part of the allocation of the array. - user3629249
when calling malloc() (and family of functions) 1) in C, do not cast the returned value. 2) always check (!=NULL) the returned value to assure the operation was successful. - user3629249
the initial result from calling malloc for the row pointers should have the resulting allocated memory set to NULLs. Then if any problem occurs, freeing the memory will be a simple loop (passing NULL to free() is ok) - user3629249

3 Answers

2
votes

If you were doing it, can you show me how you would do this?

Here's how I would implement this. I've never implemented 2d arrays in C before, fun bit of code to write.

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

void*
xmalloc(size_t n)
{
  void* p = malloc(n);
  if (p == NULL)
    {
      printf("I handle my errors!\n");
      exit(EXIT_FAILURE);
    }
  return p;
}

int**
alloc2dArray(unsigned rows, unsigned cols)
{
  int** r = xmalloc(sizeof(int*) * rows);
  for (int i = 0; i < rows; i++)
    r[i] = xmalloc(sizeof(int) * cols);
  return r;
}

void
print2dArray(int** a, unsigned rows, unsigned cols)
{
  for (int i = 0; i < rows; i++) 
    {
      for (int j = 0; j < cols; j++)
      printf("%4d", a[i][j]);
      putchar('\n');
    }
}

void
free2dArray(int** x, unsigned rows)
{
  for (int i = 0; i < rows; i++)
    free(x[i]);
  free(x);
}

int main(void)
{
  int** x = alloc2dArray(10, 14);

  for (int i = 0; i < 10; i++)
    for (int j = 0; j < 14; j++)
      x[i][j] = i*j;

  print2dArray(x, 10, 14);
  free2dArray(x, 10);

  return 0;
}

Another tip you might not be aware of: you can use valgrind on GNU/Linux to verify that you deallocated correctly:

==9322== HEAP SUMMARY:
==9322==     in use at exit: 0 bytes in 0 blocks
==9322==   total heap usage: 11 allocs, 11 frees, 640 bytes allocated
==9322== 
==9322== All heap blocks were freed -- no leaks are possible
==9322== 
==9322== For counts of detected and suppressed errors, rerun with: -v
==9322== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
1
votes

For every call to malloc, there has to be a corresponding call to free. The call to free has to use the same pointer value that was returned by corresponding call to malloc.

In your case, you have the following lines that use malloc to allocate memory.

*pA = (int **) malloc(row * sizeof(int *));
for (int i =0; i<row; ++i)
{
    (*pA)[i] = (int *) malloc( column * sizeof(int));
}

There has to be row number of calls to free, using the valus stored in (*pA).

And then, there has to be one call to free, using *pA.

Now, you can implement freeArray as:

// No need for using int ***. You are not going to modify pA
// You are just going to use the pointer.
// You don't need column in this function.

void freeArray( int ** pA, int row)
{
    for (int i =0; i<row; ++i)
    {
        free(pA[i]);
    }
    free(pA);
}

And call it from test_array_allocation using:

freeArray(pA, row);
0
votes

for this function:

void freeArray( int *** pA, int row, int column)
{

}

the parameter 'column' is not needed.

void freeArray( int **pA, int row )
{
    for( int i = 0; i < row; i++ )
    {
        free( pA[i] );
    }
    free( pA );
}