How to free 2d array in C? - c

I have the following code:
int **ptr = (int **)malloc(sizeof(int*)*N);
for(int i=0;i<N;i++)
ptr[i]=(int*)malloc(sizeof(int)*N));
How can I free ptr using free? Should I loop over ptr and free ptr[i] or should I just do
free(ptr)
and ptr will be freed?

Just the opposite of allocation:
for(int i = 0; i < N; i++)
free(ptr[i]);
free(ptr);

You will have to loop over ptr[i], freeing each int* that you traverse, as you first suggest. For example:
for (int i = 0; i < N; i++)
{
int* currentIntPtr = ptr[i];
free(currentIntPtr);
}

Yes, you must loop over ptr and free each ptr[i]. To avoid memory leaks, the general rule is this: for each malloc(), there must be exactly one corresponding free().

Simple
while (N) free(ptr[--N]);
free(ptr);
Handsome
#define FALSE 0
#define TRUE 1
typedef int BOOL;
void freev(void **ptr, int len, BOOL free_seg) {
if (len < 0) while (*ptr) {free(*ptr); *ptr++ = NULL;}
else while (len) {free(ptr[len]); ptr[len--] = NULL;}
if (free_seg) free(ptr);
}
freev(ptr, N, TRUE); /* if known length */
freev(ptr, -1, TRUE); /* if NULL-terminated */
freev(ptr, -1, FALSE); /* to keep array */
Patrician
GLib functions:
g_ptr_array_free() for freeing arrays of pointers,
g_strfreev() for freeing arrays of strings.
I find it hard to do any serious C programming without GLib. It introduces things such as dynamic strings and lays foundations for functional programming. It should really be part of the standard C run-time library. It would give C a breath of fresh air. It would make C a reasonable and competitive language again for the year 2019. But because it isn’t, it will add 1 MB to your application (either in DLL size or in executable size). Also the Windows distribution is maintained by sadists.

for(int i=0;i<N;i++) free(ptr[i]);
free(ptr);
you are not checking for malloc failure to allocate. You should always check.

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

Related

Does this free() function clean the memory?

I need your help, becouse I dont know whether I realy free the allocated memory. I also will be very grateful, if you could advice me some tools for this purpose. Thanks!
P.S You can skip bb_sort and swap functions.
#include <stdio.h>
#include <stdlib.h>
typedef struct DArray{
double * array;
int size;
} DArray;
void getArrays(DArray * arrays, int numOfArrays){
int curArraySize, i;
while(numOfArrays >= 0){
printf("Input size of array: "); scanf("%d", &curArraySize);
if(arrays[numOfArrays].array = (double*)malloc((arrays[numOfArrays].size = curArraySize)*sizeof(double))){
for(i = 0; i < arrays[numOfArrays].size; ++i)
arrays[numOfArrays].array[i] = rand()%100;
--numOfArrays;
}
else{
printf("Error, have no enough memory in the system!"); break;
}
}
}
void swap(double * arr, int pos1, int pos2) {
int tmp = arr[pos1];
arr[pos1]=arr[pos2];
arr[pos2]=tmp;
}
double * bb_sort(double * arr, int size){
int i, j, noChanges = 1;
while(1){
for(i = 0;i < size;++i){
for(j = 0;j < size-1;++j){
if(arr[j] < arr[j+1]){
swap(arr, j, j+1);
noChanges = 0;
}
}
if(noChanges) return arr;
noChanges = 1;
}
}
}
int main() {
srand (time (NULL));
int numOfArrays, i, j;
printf("Input number of arrays: "); scanf("%d", &numOfArrays);
DArray arrays[numOfArrays];
getArrays(arrays ,numOfArrays-1);
for(i = 0; i < numOfArrays; ++i){
bb_sort(arrays[i].array, arrays[i].size);
}
for(i = numOfArrays-1; i >= 0; --i){
printf("\nSorted array num#%d\n", i+1);
for(j = 0; j < arrays[i].size; ++j)
printf(" %.1lf ", arrays[i].array[j]);
free(arrays[i].array); <------FREE MEMORY?
printf("\n");
}
printf("Done!");
while(1){
}
return 0;
}
=====================================================================================================
Short Answer:
The OP ask if 'memory is cleaned'. Technically, there is no requirement for the free implementation to CLEAN the memory (e.g, sets the data to zero, or some random data). Most implementation will not CLEAR to memory to save time.
If, by mistake, the code will try to read the data, it will usually find the data is still in memory, potentially modified by the free call, or by other code, which was assigned the freed memory to other tasks.
For security sensitive information (password, credit card numbers, private keys), it is common to ZERO the data, or to fill the region with other pattern, before calling free. It will make it harder/reduce the risk of the data being access by mistakes, bugs or hacking.
Some memory debuggers will fill freed memory with pattern data/guards/etc, to help detect memory problems earlier than later.
Yes it will, since your program created array pointer using malloc function, and it does not manipulate that pointer, according to C99 standard (ISO/IEC 9899:1999):
7.20.3.2 The free function (p: 313):
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

How should I free an array in C?

I created a function to free an array in C, but I don't know
whether it is correct or not:
void dealloc_array(void *array[], int size) {
int i = 0;
for (i = 0; i < size; i++) {
if (array[i]) free(array[i]);
}
if (array) free(array);
}
I'm not sure whether I should execute free(array) at the end. Technically, we've already freed all the array elements, so we don't need to do free(array).
Thanks for the help.
If you malloc the pointer as well as each element of the array you will need to free that pointer after your for loop.
For example:
int **array;
array = malloc(SIZE*sizeof(int*));
for(int ii = 0; ii < SIZE; ii++)
{
array[ii] = (int*)malloc(sizeof(int));
}
you will have to free each element and free array.
Essentially for every malloc/calloc you have, you must have a free
You must write free(array) at the end, otherwise there will be memory leak.

Dynamic array cleanup when malloc returns null

I am wondering what is the best way to clean up memory which was already allocated during the failed creation of 2D array.
int** a = (int**)malloc(rows * sizeof(int*));
for (int i = 0; i != rows; ++i)
a[i] = (int*)malloc(columns * sizeof(int));
for (int i = 0; i != rows; ++i)
free(a[i]);
free(a);
The sample code above should work like a charm. However malloc can return null and when it will the code above will not handle the problem. How can we protect such case?
Let's say (int*)malloc(columns * sizeof(int)) returned null for i = 3. We already have allocated space for int** a and a[0], a[1] and a[2].
Here is my current approach. Ugly and not sure if correct. This is why I am asking you for help.
int rows;
int columns;
scanf("%d", &rows);
scanf("%d", &columns);
int** a = (int**)malloc(rows * sizeof(int*));
if (!a)
{
printf("Cannot allocate enough space."); // nothing to clean up here
return 1; // to make example easier
}
int i;
bool arrayCreated = true;
for (i = 0; i != rows; ++i)
{
int* tmp = (int*)malloc(columns * sizeof(int));
if (!tmp) // malloc returned null
{
arrayCreated = false; // let's mark that we need to do some cleanup
break;
}
a[i] = tmp;
}
if (!arrayCreated) // creation failed, clean up is needed
{
for (int j = 0; j <= i; ++j)
free(a[j]);
}
else
{
for (int i = 0; i != rows; ++i)
free(a[i]);
}
free(a);
In short:
As you have different functions used to allocate memory, you'll need to call their counterpart deallocation functions accordingly:
malloc(), calloc() and realloc() need to be deallocated with a call to free()
X* x = new X(); needs to be deallocated with delete x;
X** x = new X[10]; needs to be deallocated with delete[] x;
The idiomatic way in c++ is to use either a container
std::vector<X> x;
or a smart pointer like
std::unique_ptr<X> x = std::make_unique<X>();
to redeem you from caring about the necessary bookkeeping to balance allocation/deallocation operations correctly.
Please notice that this is a theoretical question about error handling in such, specific cases. I want to highlight that first two cases are for C, not C++.
There's no standard error handling defined if you're using the wrong pairs of dynamic memory de-/allocation functions.
As mentioned above they need to pair like described. Anything else calls undefined behavior.
int** b = (int**)calloc(sizeof(int*) * rows, sizeof(int*));
This is not correct, the first parameter of calloc is "number of elements to allocate".
should be
int** b = (int**)calloc(rows, sizeof(int*)); /* No need to cast in C */
What is the safe way for creating multidimensional arrays in C and C++
for such scenarios?
In C (in order to avoid segmentation) a real 2D dynamic array should be declared as
int (*arr)[columns]; /* A pointer to an array of n ints */
and (m)allocated using
arr = malloc(sizeof(int [rows][columns]));
or
arr = calloc(rows, sizeof(int[columns]));
In this way a single call to free(arr); is enough.
I'm not sure about C, but C++; delete[] should suffice.

Dynamic memory allocation repetition in C

I am somewhat new to C programming. I have a doubt regarding dynamic memory allocation. The following is a code in the main program for memory allocation.
double **mat=(double**)malloc(sizeof(double*)*n);
mat[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
mat[i] = mat[i-1] + n;
mat = create_square_matrix(n);
I want to call the function and create elements in the matrix inside the function. Do I have once again allocation memory inside the function like below or Is there any other method to avoid this tedious memory allocation repetition. Following is the function.
`double** create_square_matrix(int n)
{
int i,j,sum=0;
double **array2=(double**)malloc(sizeof(double*)*n);
array2[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
array2[i] = array2[i-1] + n;
for (i = 0; i < n; ++i)
{
for (j = 0; j < n; ++j)
{
sum=sum+j;
array2[i][j]=sum;
}
}
return array2;
}
`
The above function returns the array which is stored in the 'mat' variable. And another question is how do I free the memory of variable 'array2' inside the function after using the return method. I can't free the memory possibly before returning the array. Is there a method to free the memory in the above function.
Your function create_square_matrix allocates memory and then fills it by some values.
Your top piece of code allocates memory, and then calls create_square_matrix which again allocates memory. It is like to mop floors before calling the janitor who also mops floors. You don't need to allocate memory twice. Not only it is unneccessary, in fact it is bad. Since you perform two allocations, the memory from the first one is lost, and there is no way to free it. This is called memory leak. Instead of
double **mat=(double**)malloc(sizeof(double*)*n);
mat[0]=(double*)calloc(sizeof(double),n*n);
for(i=1; i<n; i++)
mat[i] = mat[i-1] + n;
mat = create_square_matrix(n);
you should write
double **mat = create_square_matrix(n);
As mentioned, in C there's no need to cast to/from void*. Also, your calloc is backwards: use N elements for the first argument, sizeof(element) for the second.
I will answer your question, and then suggest a better approach.
You are choosing double ** for your matrix. Even if it weren't square, you know exactly how many pointers and how many doubles you need, and of course how big each type is. So,
double **M = malloc( n * sizeof(double*) + n * m * sizeof(double) );
does the trick, does it not? If sizeof(double*) == sizeof(double) for your machine (probably true), then
double **M = calloc( (1+n) * m, sizeof(double) );
works, too, but less portably. You also get the zeros for free; you'll have trouble finding a machine for which it's not true that double f=0 yields a value for which all bits are zero.
But why define your matrix as an array of pointers? Why not instead define it as an array of doubles?
double *M = calloc( n * m, sizeof(double) );
Better yet, for the past 15 years or so, C has supported variable-length arrays, meaning you can define arrays whose size is determined at runtime. Back in K&R days, you could define an array M[n] unless n was a static constant or enum. If your arrays aren't ginormous -- meaning that for the machine in question they'll fit comfortably on the stack -- you can skip malloc and simply define your matrix by a size determined at runtime.
Even if you can't do that, can typedef one dimension dynamically,
typedef double (x_axis_t)[m];
double x_axis_t *M = calloc( n * sizeof(x_axis_t), sizeof(double) );
which is nice, because then you can access your array as
M[x][y];
Just don't try to use M[x,y], because that's something else altogether.
BTW, since you're new to the game, to use a c99 compiler, the standard command is c99, not cc. See your friendly manual for details. :-)
Using a nice function macro for memory allocation is always a good idea. Unless you have to free memory manually I would leave it to a garbage collector such as libgc. Below is an example. If you don't want to use a garbage collector you can just replace GC_MALLOC with malloc. When you free the array (manually) you must first free the individual rows.
#include <gc/gc.h>
#include <stdio.h>
#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = GC_MALLOC((n) * sizeof (ptr)[0])
double **SquareMatrix(int n)
{
double **A;
int i, j;
NEW_ARRAY(A, n);
for (i = 0; i < n; i++) {
NEW_ARRAY(A[i], n);
for (j = 0; j < n; j++) {
A[i][j] = 0.0;
}
}
return A;
}
int main(void)
{
const int n = 5;
double **A;
int i, j;
A = SquareMatrix(n);
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
printf("%5.2f ", A[i][j]);
}
putchar('\n');
}
return 0;
}

Freeing a 2-d char array

After using this function to allocate a 2-d array:
char** make_matrix(int M, int N)
{
char** MAT = (char**)malloc(M * sizeof(char));
for (int i = 0; i < M; i++)
{
MAT[i] = (char*)malloc(N * sizeof(char));
}
return MAT;
}
I found that trying to free(M[0]) causes an assertion failure. All that I can find relating to freeing 2-d arrays use int instead of char. Yet replace every char with int above and the assertion failure disappears. Why is this, and how can I then free the entire 2-d array?
You are allocating too little memory for MAT. Change relevant line to:
char** MAT = (char**)malloc(M * sizeof(char*));
This is because MAT is array of pointers, not characters. Since your code did not allocate enough memory, it was likely writing outside of array bounds and corrupting memory.
It could work with integers because they are bigger, so with some luck you could have been allocating just enough memory (at least on 32 bit machine).
The first malloc call is M * sizeof(char) instead of sizeof(char *). The sizeof(char) would be 1 byte, the size of a char* is likely 4 bytes.
Edit: I see someone beat me to the punch. Accept the other guy's answer.
You should iterate through all the rows of the matrixes and free them first, and then finally the MAT
something like this:
void free_matrix(int M)
{
for (in i = 0; i < M; i++)
{
free(MAT[i]);
}
free(MAT);
}
To release the space (assuming it is correctly allocated), you need a call to free() corresponding to each call to malloc().
void destroy_matrix(char **MAT, int M)
{
for (int i = 0; i < M; i++)
free(MAT[i]);
free(MAT);
}
Your code works when you replace char with int because sizeof(int) == sizeof(int *) on your (32-bit) system. It's largely by coincidence; you'd be in trouble again on a 64-bit system.

Resources