As noted in a comment, within broad limits, if your code encounters an allocation error, you correctly release all the data that was allocated prior to the error.
You will need a function to release the allocated memory; it will need to know how many rows to release. You could use that in your error recovery, using l
as the number of rows to be released.
void deallocate(double **matrix, int rows)
{
for (int i = 0; i < rows; i++)
free(matrix[i]);
free(matrix);
}
That does not set the pointer passed in to null; you can use a three-star interface if you insist, but it probably isn't worthwhile (IMO — YMMV). This can then be used in the allocation code.
void allocate(double ***m, int r, int c)
{
*m = (double **)malloc(sizeof(double *) * r);
if (*m == NULL)
return;
for (int l = 0; l < r; l++)
{
(*m)[l] = (double *)malloc(sizeof(double) * c);
if ((*m)[l] == NULL)
{
deallocate(*m, l);
*m = NULL;
return;
}
}
}
There are those who are fanatical about 'no cast on malloc()
' — I am not one of those, but I do make sure my code doesn’t compile in my development environment if <stdlib.h>
was not included (so there was no declaration of malloc()
et al viable when it is called). That makes it safe for user’s too, even if they don’t compile with the rigorous warning/error options I use.
Note too that Three-star Programmer is not a compliment. As suggested in the comments, you could use a different interface:
double **allocate(int r, int c)
{
double **matrix = (double **)malloc(sizeof(double *) * r);
if (m == NULL)
return NULL;
for (int l = 0; l < r; l++)
{
matrix[l] = (double *)malloc(sizeof(double) * c);
if (matrix[l] == NULL)
{
deallocate(matrix, l);
return NULL;
}
}
return matrix;
}
Note that because the allocation (and deallocation) functions use int
and not size_t
for the size parameters, you could get negative values. You could also get zeros provided — but if the size is zero, the code will 'work' safely, but the result will be unusable (no space allocated).