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.
Related
I have a program i made and its running perfectly! the only problem is the free pointers function
this is a link for the full code https://codeshare.io/aVE3n3
The problem is that i success to free the player name pointer, but after the program doesn't let me free the player's pointer.
I'd love to get some help, thanks.
void freeTeam(team* t,int size)
{
int temp;
for (int j = 0; j < size; j++)
{
temp = t[j].current_players;
for (int i = 0; i < temp; i++)
{
free(t->players[i].name);
}
free(t->players);
for (int i = 0; i < temp; i++)
{
free(t[i].team_name);
}
free(t[j]);
}
}
The first wrong part is
t->players = (player**)calloc(t->max_players, sizeof(player*));
in initTeam().
t->players has type player* and its element type is player.
In typical environment, player (one pointer and other elements) consume more memory than player* (one pointer), so you won't allocate enough memory here.
It should be
t->players = calloc(t->max_players, sizeof(player));
or
t->players = calloc(t->max_players, sizeof(*t->players));
(note: c - Do I cast the result of malloc? - Stack Overflow)
The second wrong part is the freeTeam function.
free(t->players[i].name); may cause double (or more) free because only t[0] is dealt with.
free(t[i].team_name); may cause double (or more) free and/or out-of-bounds read because the usage of loop is wrong.
free(t[j]); is invalid because structure is not a pointer.
It should be
void freeTeam(team* t,int size)
{
int temp;
for (int j = 0; j < size; j++)
{
temp = t[j].current_players;
for (int i = 0; i < temp; i++)
{
free(t[j].players[i].name);
}
free(t[j].players);
free(t[j].team_name);
}
}
after that, t should be freed after freeTeam(t,size); in main().
Additionaly, you should use standard int main(void) in hosted environment instead of void main(), which is illegal in C89 and implementation-defined in C99 or later, unless you have some special reason to use non-standard signature.
My goal is to dynamically reallocate memory for a two dimensional int array in C. I know there are already several questions about that topic, but unfortunately my code does not run properly and i don't know what is going wrong.
First i am allocating memory:
int n = 10;
int m = 4;
int** twoDimArray;
twoDimArray = (int**)malloc(n * sizeof(int*));
for(int i = 0; i < n; i++) {
twoDimArray[i] = (int*)malloc(m * sizeof(int));
}
And initializing the array with integer numbers:
for(int i = 0; i < n; i++) {
for(j = 0; j < 4; j++) {
twoDimArray[i][j] = i * j;
}
}
Then i use realloc() to reallocate memory dynamically:
int plus = 10;
int newArraySize = n + plus;
twoDimArray = (int**)realloc(twoDimArray, newArraySize * sizeof(int));
I am expecting my aray twoDimArray to be accessible at [10][0] now, but when running
printf("twoDimArray[10][0] = %d\n", twoDimArray[10][0]);
i get an "EXC_BAD_ACCESS" runtime error.
Probably i am missing something rather simple, but since i am new to C and can't figure out my mistake. Any help is appreciated.
reallocating the array of pointers is necessary, but then you have only n values that point to something valid. You need to allocate the rest of the sub-arrays because the newly allocated memory points to unallocated/invalid areas. The error is not from accessing the pointer, but from dereferencing it.
You need to add something like:
for(int i = n; i < n+plus; i++) {
twoDimArray[i] = malloc(m * sizeof(int));
}
(same goes for deallocation: first deallocate the arrays in a loop, then deallocate the array of pointers)
Aside:
assigning the result of realloc directly to the original variable can be a problem if realloc returns NULL. Even if it's rare in those resizing cases (Under what circumstances can malloc return NULL?), you should copy the result in a temp variable, check for NULL, and free the old pointer if reallocation failed.
Do I cast the result of malloc?
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.
I have a newbie question regarding array and functions in C.
Let's say I have this array:
int array1[10] = {2,4,6,3,2,3,6,7,9,1};
I wrote this function:
int *reverseArray(int *array, int size)
{
int *arr = malloc(size * sizeof(int));
int i, j;
for(i = 10, j = 0; i > 0; i--, i++) {
arr[j] = array[i];
}
return arr;
}
I don't even know if it works, because if I do:
array1 = reverseArray(array1, 10);
I got the error:
assignment to expression with array type
How do I assign the adress of an array to another array?
The function is correct*, and it works fine. The problem is that you cannot assign an array like this:
array1 = reverseArray(array1, 10);
reverseArray returns a pointer, so you should assign it to a pointer variable:
int* reversedArray1 = reverseArray(array1, 10);
If you want the data to be placed back in array1, use memcpy:
memcpy(array1, reversedArray1, sizeof(array1));
free(reversedArray1);
Note that since your function uses malloc to allocate its return value, the caller needs to deallocate this memory after it is done with it. You need to call free(reversedArray1) to ensure that the allocated array does not create a memory leak.
* Use size-1 in place of 10 in the for loop header, since you are passing it anyway, and allow i to reach zero:
for(i = size-1, j = 0; i >= 0; i--, j++)
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);
}