I was given a task to implement a simple API for fully dynamic 2D array according to following interface.
const int m = 2;
const int n = 3;
int **array = allocate_array (m, n);
assert (array != NULL);
for (unsigned int i = 0; i < m; i++)
{
for (unsigned int j = 0; j < n; j++)
{
array[i][j] = i*10 + j;
}
}
print_array (array, m, n);
free_and_nullify_array (&array, m);
printf("array points to %p\n", array);
/*
OUTPUT:
0 1 2
10 11 12
array points to (nil)
*/
I need to implement only 3 specific functions as part of the program.
While I have made an attempt to implement these functions, the program is currently indicating the presence of memory leaks. Despite my efforts, I was unable to identify the exact locations within the code where these memory leaks are occurring.
//! allocate an m x n fully-dynamic 2D array
int** allocate_array (int m, int n)
{
int ** arr = malloc (sizeof(int *) * m);
if (!arr)
{
free(arr);
arr = NULL;
return NULL;
}
for (int i = 0; i < n; i++)
{
arr[i] = malloc (sizeof(int) * n);
if (!arr[i])
{
free(arr[i]);
arr[i] = NULL;
return NULL;
}
}
return arr;
}
//! free *array, a full-dynamic 2D array with m rows
//! and set its pointer to NULL
void free_and_nullify_array (int ***p_array, int m)
{
for (int i = 0; i < m; i++)
{
free((*p_array)[i]);
(*p_array)[i] = NULL;
}
free(*p_array);
*p_array = NULL;
}
//! print an m x n fully-dynamic array
//! use one line per row, 2 digits per integer ("%2d"), one space
void print_array (int **array, int m, int n)
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
printf("%2d ", array[i][j]);
}
printf("\n");
}
}
>Solution :
For starters you have a typo in this for loop
for (int i = 0; i < n; i++)
^^^^^
{
arr[i] = malloc (sizeof(int) * n);
if (!arr[i])
{
free(arr[i]);
arr[i] = NULL;
return NULL;
}
}
You need to use the variable m instead of n.
Another problem in this for loop is if a memory was not allocated successfully then the memory allocated previously for the array of pointers and for one-dimensional arrays of integers is not freed.
You should write for example
//! allocate an m x n fully-dynamic 2D array
int ** allocate_array( int m, int n )
{
int **arr = malloc( m * sizeof( int * ) );
if ( arr != NULL )
{
int i = 0;
while ( i < m && ( arr[i] = malloc( n * sizeof( int ) ) ) != NULL ) i++;
if ( i != m )
{
for ( int j = 0; j < i; j++ ) free( arr[j] );
free( arr );
arr = NULL;
}
}
return arr;
}
In general you should check that values of the parameters are positive values. And instead of using the signed integer type int for the parameters it will be much better to use the unsigned integer type size_t.
For example
//! allocate an m x n fully-dynamic 2D array
int ** allocate_array( size_t m, size_t n )
{
int **arr = NULL;
if ( m != 0 && n != 0 )
{
int **arr = malloc( m * sizeof( int * ) );
if ( arr != NULL )
{
size_t i = 0;
while ( i < m && ( arr[i] = malloc( n * sizeof( int ) ) ) != NULL ) i++;
if ( i != m )
{
for ( size_t j = 0; j < i; j++ ) free( arr[j] );
free( arr );
arr = NULL;
}
}
}
return arr;
}
And within the function free_and_nullify_array this statement
(*p_array)[i] = NULL;
is redundant. You may remove it.