I have this code segment:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int ** ar;
int i;
ar = malloc( 2 * sizeof(int*));
for(i=0; i<2; i++)
ar[i] = malloc ( 3 * sizeof(int) );
ar[0][0]=1;
ar[0][1]=2;
ar[0][2]=5;
ar[1][0]=3;
ar[1][1]=4;
ar[1][2]=6;
for(i=0; i<2; i++)
free(ar[i]);
free(ar);
printf("%d" , ar[1][2]);
return 0;
}
I went through some threads on this topic
(how to free c 2d array)
but they are quite old and no one is active.
I had the following queries with respect to the code:
Is this the correct way to free memory for a 2D array in C?
If this is the correct way then why am I still getting the corresponding array value when I try to print ? Does this mean that memory is not getting freed properly ?
What happens to the memory when it gets freed? Do all values which I have stored get erased or they just stay there in the memory which is waiting for reallocation?
Is this undefined behaviour expected?
Yes you have two levels or layers (so to speak) of memory to free.
The inner memory allocations (I like how you do those first)
The outer memory allocation for the topmost int** pointer.
Even after you freed the memory, nothing was done with it to overwrite it (So yes it's expected). Hence why you can still print them to the console. It's a good idea to always NULL your pointers after you are done with them. Kind of the polite thing to do. I've fixed many bugs and crashes in the past because the code did not null the pointers after freeing them.
In Microsofts Visual Studio, with the Debug C runtime, it can overwrite the newly free'd values with some garbage that will immediately raise an access violation if used, or dereferenced. That's useful for flushing out bugs.
It looks like you are new to C (Student?). Welcome and have a fun time.
Related
This question already has answers here:
No out of bounds error
(7 answers)
Closed 3 years ago.
I am expecting the following snippet to allocate memory for five members using calloc.
$ cat calloc.c
// C program to demonstrate the use of calloc()
// and malloc()
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *arr;
arr = (int *)calloc(5, sizeof(int));
printf("%x\n", *arr);
printf("%x\n", *(arr+1));
printf("%x\n", *(arr+2));
printf("%x\n", *(arr+3));
printf("%x\n", *(arr+4));
printf("%x\n", *(arr+5));
printf("%x\n", *(arr+6));
// Deallocates memory previously allocated by calloc() function
free(arr);
return(0);
}
But it seems to be allocating more than five; it is allocating six members, why?
./a.out
0
0
0
0
0
0
411
Allocating memory isn't like buying lollipops. Allocating memory is more like buying land.
If you buy five lollipops and you try to eat the sixth one, this obviously doesn't work — it's pretty nonsensical to even talk about "trying to eat the sixth one".
But if you buy a ten foot by fifty foot plot of land, and you start putting up 10x10 foot buildings, and after building five of them (completely occupying your land), you build a sixth one encroaching over onto your neighbor's land, your neighbor might not notice right away, so you might get away with it. (For a little while, anyway. There's bound to be trouble in the end.)
Similarly, if you allocate an array of size 5 and then try to access a nonexistent 6th element, there's no law of nature that prevents it the way there was when you tried to eat the nonexistent 6th lollipop. In C you don't generally get an error message about out-of-bound array access, so you might get code that seems to work, even though it's doing something totally unacceptable, like encroaching on a neighbor's land.
First of all, let's get something clear: for all purposes, *(a+x) is the same as a[x].
C has free memory access. If you do arr[1000], you will still get a value printed, or the program will crash with a segmentation fault. This is the classic case of undefined behaviour. The compiler cannot know whether the code you wrote is wrong or not, so it cannot throw an error. Instead, the C standard says this is undefined behaviour. What this means is that you are accessing memory you shouldn't.
You, as the programmer, are responsible to check that you don't go out of bounds of the array and not the compiler. Also, calloc initializes all elements with 0. Why do you think you got 411? Try running it again, you will probably get a different value. That memory you are accessing at a[5] is not allocated for the array. Instead, you are going out of the bounds of the array. That memory could have very well been allocated to something else. If it was allocated to another program, you would get a segmentation fault when you run the program.
It hasn't allocated memory more than 5. It has allocated 5 members and initialized them with 0. When you access to outside of the allocated memory, it may be written anything into it, and not certainly a non zero value.
Every time a malloc, calloc or realloc is called, the memory allocation is done from heap area.
Run Time/ Dynamic allocation -> Heap
Static/Compile Time-> Stack
// C program to demonstrate the use of calloc()
// and malloc()
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *arr;
arr = (int *)calloc(5, sizeof(int)); // dynamically allocate memory for 5 element each of size of integer variables and intializes all with 0.
printf("%x\n", *arr);//array name is a constant pointer(points to base address of the array
printf("%x\n", *(arr+1));
printf("%x\n", *(arr+2));
printf("%x\n", *(arr+3));
printf("%x\n", *(arr+4));
printf("%x\n", *(arr+5));
printf("%x\n", *(arr+6));// you are accessing memory which is not the part of your pointer variable. There are chances that this is the part of the some other program or variable.
// Deallocates memory previously allocated by calloc() function
free(arr);
arr=NULL;//always assign pointer to null to avoid any dangling pointer situation
return(0);
}
I'm just starting to learn coding in c, and I have a few questions regarding 2d matrices in combination with the free() command.
I know that you first need to create an array with pointer, pointing to the different columns of the matrix:
double **array = (double **)malloc(5*sizeof(double *));
for(int n = 0; n<5; n++){
array[n] = (double *) malloc(6*sizeof(double));
I know that the correct way to then deallocate this matrix is to first deallocate the individual rows and then the array pointer itself. Something along the lines of:
for (i = 0; i < nX; i++){
free(array[i]); }
free(array);
My question is: Why is this necessary? I know that this incorrect, but why can't you just use: free(array)? This would deallocate the pointer array, to my understanding. Won't the memory that is used by the columns just be overwritten when something else needs acces to it? Would free(array) lead to corrupted memory in any way?
Any help is much appreciated!
Your code, not only allocate memory for array of pointers (the blue array), but in the for loop, you also allocate memory for the red arrays as well. So, free(array) line, alone, will just free the memory allocated by the blue array, but not the red ones. You need to free the red ones, just before loosing the contact with them; that is, before freeing the blue array.
And btw;
Won't the memory that is used by the columns just be overwritten when something else needs acces to it?
No. The operating system will keep track of the memory allocated by your process (program) and will not allow any other process to access the allocated memory until your process terminates. Under normal circumstances —I mean, remembering the C language not having a garbage collector— the OS never knows that you've lost connection with the allocated memory space and will never attempt like, "well, this memory space is not useful for this process anymore; so, let's de-allocate it and serve it for another process."
It would not lead to corruption, no, but would create a memory leak.
If done once in your program, it probably doesn't matter much (a lot of professional/expensive applications have - small,unintentional - memory leaks), but repeat this in a loop, and you may run out of memory after a while. Same thing if your code is called from an external program (if your code is in a library).
Aside: Not freeing buffers can be a useful way (temporarily) to check if the crashes you're getting in your programs originate from corrupt memory allocation or deallocation (when you cannot use Valgrind). But in the end you want to free everything, once.
If you want to perform only one malloc, you could also allocate one big chunk, then compute the addresses of the rows. In the end, just deallocate the big chunk (example here: How do we allocate a 2-D array using One malloc statement)
This is needed because C does not have a garbage collector.
Once you allocate memory with malloc or similar function, it is marked as "in use" for as long as your program is running.
It does not matter if you no longer hold a pointer to this memory in your program.
There is no mechanism in the C language to check this and automatically free the memory.
Also, when you allocate memory with malloc the function does not know what you are using the memory for. For the allocator it is all just bytes.
So when you free a pointer (or array of pointers), there is no logic to "realize" these are pointers that contain memory addresses.
This is simply how the C language is designed: the dynamic memory management is almost1 completely manual - left to the programmer, so you must call free for every call to malloc.
1 C language does handle some of the more tedious tasks needed to dynamically allocate memory in a program such as finding where to get a free continuous chunk of memory of the size you asked for.
Let's take this simple example:
int **ptr = malloc(2*sizeof *ptr);
int *foo = malloc(sizeof *foo);
int *bar = malloc(sizeof *bar);
ptr[0] = foo;
ptr[1] = bar;
free(ptr);
If your suggestion were implemented, foo and bar would now be dangling pointers. How would you solve the scenario if you just want to free ptr?
I created array with 10 integer size using malloc. I added values to the elements. Then, I reallocated it to 200 bytes into newArr. And then I reallocated newArr into newArr2 with size of 10 integers again. Code:
void main(){
int i, *arr = (int *)malloc(10* sizeof(int));
for(i=0; i<10; i++){
arr[i] = i;
}
int *newArr = (int *)realloc(arr, 200);
int *newArr2 = (int *)realloc(newArr, 10* sizeof(int));
}
How should I use free to remove all the allocated memory here? I'm getting error while clearing all of them.
Edit: As per the accepted answer the old memory should've been cleared but it didn't. I was able to access memory and was able to change value on old address.
From my point of view, when you use malloc or realloc you're changing the memory reference, so, if you call realloc on a variable you are freeing the old space used and allocate new space, copying the old data to the new memory position, so, in your example, arr doesn't hold a valid memory address after first realloc. The same thing happen on newArr
realloc is basically malloc with the new size, memmove the data to the new block and free the old one. (But implementation can optimize this process because they've got more information they can use, like just extending the current allocated block, producing the same pointer)
So the pointers arr and newArr are invalid and shouldn't be accessed anymore because they might have been freed, so the pointer in newArr2 is the current one and valid, if the previous allocations didn't fail. So free(newArr2) is the correct answer.
Sure, you might access the memory from the old pointers, but it isn't guaranteed because it might've been allocated and overwritten for a different purpose or you might just be lucky to get the same pointer back from realloc (because from eg. the optimization above). It's just undefined behavior when accessing freed memory.
Source on reddit
I'm creating a 2D Array in C; am I freeing it correctly?
// create
int n = 3;
int (*X)[n] = malloc(sizeof(int[n][n]));
// set to 0
for(int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
X[i][j] = 0;
}
}
// is this all I need?
free(X);
You must call free once for each malloc. Your code has one malloc and one free (with the same address) so it is correct.
For every malloc(), there must be a matching free(). So if you call malloc() in a loop, there must be a similar loop later on that calls free() just as many times. Your code has one malloc() and one corresponding free(), so yes, you have freed everything you need to.
The most common way I've seen to allocate a two-dimensional array is to do something like:
int **arr = malloc(sizeof (int *) * num_rows);
for (i = 0; i < num_rows; ++i)
arr[i] = malloc(sizeof (int) * num_cols);
/*
* Using `sizeof *arr` and `sizeof **arr`
* respectively would have been more safe,
* but for the purpose of this example, I think
* using `int *` and `int` is simpler to
* understand.
*/
then later to free:
for (i = 0; i < num_rows; ++i)
free(arr[i]);
free(arr);
This makes the outer dimension hold num_row pointers to pointers to int (each of the num_row pointers points to the starting address of the 'column'). So each element in the outer dimension points to a row, and in each row there are num_cols elements in the inner dimension (the 'columns'), which is just a group of num_cols integers. Does this make sense to you? So you have to allocate num_rows integer pointers, and each one of these points to the first 'column' of that row--for each row you have to allocate space for num_cols integers, so you can see the loop will make a total of num_rows * num cols integers, and they way they are allocated allows you to use array indexing notation (two-dimensional in this case--each element in the outer dimension points to the start of a 'row', which contains a pointer to the start of a 'column', hence the double pointer) to access the elements. I know this is probably confusing, that is why I tried to describe it so many different times/ways, but please just ask any questions, especially about what you don't understand in particular, and I will be more than happy to work with you in helping understand it.
I'm not saying you have to create your 2-D array this way; your way works fine too, I just wanted to show you this way since you are likely to run into it since it's very common.
Also, look into Valgrind. You can use that tool to see if you have forgotten any free()s / have an unmatched malloc(), and lets you know if there is any allocated memory unreachable/leaked (maybe the pointer was changed before the call to free() so the call doesn't properly free the memory and you get a leak).
RastaJedi - another couple of things to note:
After a call to free(), it's a good idea to set the free'd variable to NULL, which helps prevent use after free.
Also, if you malloc in one block of code, then free in some called function, and then return from that function, sometimes C forgets about the final free (in your example, free(arr) ), and you should set the variable to NULL upon return.
I came here, and verified that the malloc and free calls that I wrote in the code I'm working on are indeed exactly as your "common" way, but kept running into a Seg Fault, because I was using malloc from in main, free-ing from a helper function which received the double-indirect head of the array. Having that all wrapped in a while-loop for user interaction, a second pass around was checking the array head for NULL-ness, but not seeing it as NULL, despite explicitly setting to NULL inside the helper function. Crawling thru the code with a debugger is how I identified the behavior, and why I came looking.
After being free'd, the memory is available, and variously (and randomly) reassigned; when the function with the free() calls returns, the memory that was allocated has been released, however it seems that the calling code still holds a pointer to that place in memory. There then exists a possible race-condition; by the time the calling code regains control, there's no guarantee as regards the location pointed to by the variable used for the array head, and therefore it's a very good idea to set the variable to NULL after the function returns.
Although you can use malloc'd pointers for pass-by-reference behavior, after a call to free() inside some function, the by-reference behavior breaks (because the thing being referenced is what has been free'd).
So, thank you for your answer, which confirmed that I was looking at the wrong part of my problem - just figured maybe someone else may stumble here, and possibly have the same issue I did.
i have a little question in relation to the free() function of C.
I allocate in a program a multidimensional array with this code :
char **newMatrix( int N ){
int i,j;
char **a = malloc(sizeof *a * N);
if (a)
{
for (i = 0; i < N; i++)
{
a[i] = malloc(sizeof *a[i] * N);
}
}
at the end of the program the array is full of characters.
So i do this to deallocate the memory.
void freeArray(char **a, int m){
int i;
for (i = 0; i < m; ++i) {
free(a[i]);
}
free(a);
}
My question is , how can I really check if the free() function works well , and deallocate all the memory?
I ask you because I have tried to print the matrix after the freeArray , and the result is that the values are still stored in the a[i][j] columns and rows .
Sorry if it will be a stupid question , i'm new of C programming!
free does not mean that it will actually delete the memory! It will inform to the OS that I don't want this memory any more, use it for some other process!
You can certainly continue to use array a after calling free(a) and nothing will stop you. However the results will be completely undefined and unpredictable. It works by luck only. This is a common programming error called "use after free" which works in many programs for literally years without "problems" -- until it causes a problem.
There are tools which are quite good at finding such errors, such as Valgrind.
free will not clear the memory for you. It just marks it as available for the OS to reallocate somewhere else. People tend to assign NULL to a pointer after freeing to prevent accidental reuse. If you want to be sure what your code is doing, you could memset the allocated space to a known value before freeing. To be honest, just print out how much data you mallocate and make sure you free the same size of data from the same pointer.
free() will only remove the reference to memory pointed to, by the pointer passed to it.
Once a pointer is passed to free() and the free() returns a success(which always is..), the pointer should never be used.
To avoid this usage, which is a illegal reference, a pointer variable should always be assigned NULL after it is passed to free().
If I understood you correctly you want to check if:
You don't reuse memory after freeing it
You freed all of the memory
It's not possible to do it directly from within language - however there are tools which can help. For example Valgrind can check both of those things (and much more). If you are on Windows tools like UMHD can be helpful but I haven't found any freeware replacement (though see also "Is there a good Valgrind substitute for Windows?" question)