Why free() for array of poiters does not deallocate memory? - c

I'm trying to free memory after pointers array as in a following code:
int ** t = (int**) malloc(sizeof(int*)*10000000);
printf("1\n");
getchar();
for(int i =0; i < 10000000; i++){
t[i] = (int*) malloc(sizeof(int));
*t[i] = i;
}
printf("2\n");
getchar();
for(int i =0; i < 10000000; i++){
free(t[i]);
}
printf("3\n");
getchar();
free(t);
printf("4\n");
getchar();
During the execution my system monitor shows me some strange values. When specific numbers are displayed (as in the code) i get following memory usage.
148K
390,540K
390,540K
312,676K
I'm a bit confused. Why numbers in 2 and 3 are the same? Am I doing something wrong, or system monitor is inaccurate? If it is fault of SM then why it noticed difference between 3 and 4?

The behavior of free() depend on its underlying implementation. Most of the implementations of free()does not return the freed memory back to the OS but just gives the memory back to the pool, from which the malloc requests are satisfied, which simply means the freed memory is now available to reuse by the program. Check this.

Related

Where to free memory, while creating 2d array? valgrind error

I am starting to learn dynamic memory allocation. In this code, I have created in main function 2d array:
int r, c;
scanf("%d %d\n", &r, &c);
size_t row = (size_t) r;
size_t col = (size_t) c;
int **board = malloc(row * sizeof(*board));
for (int i = 0; i < r; i++) {
board[i] = malloc(col * sizeof(*board[i]));
}
(I need both int and size_t because of for loops, especially when r>=0, which is always true for size_t).
Then I change the board with other functions. Valgrind returs:
==59075== 364 (56 direct, 308 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==59075== at 0x483577F: malloc (vg_replace_malloc.c:299)
==59075== by 0x10B4DB: main (name22.c:122)
==59075==
122 line is:
int **board = malloc(row*sizeof( *board));
I suppose I have to use free(), but after checking other answers I don't know, where is my mistake and where to put free(), if use use this table through the rest of the program. I would appreciate your hints and explanations.
`
When you call int **board = malloc(row * sizeof(*board)); , the system will allocate you row * sizeof(*board) bytes of memory and then return a pointer to the start of that memory (ie - a memory address), which you are storing in the int ** variable called board.
When your program finishes, the system will reclaim that memory, so if your program is short lived, it probably doesn't matter very much, but it's good practise to get into the habit of freeing your memory because it will not reclaim any memory at all until your program exits, unless you tell it to.
For that reason, you should always call free(...), passing in the memory address you were given when you first called malloc(...), once you are done with that memory. In most cases, each call to malloc(...) should have an equal and opposite call to free(...)
This is important because your system has a finite amount of memory. If your program is asking for resources and then never giving them back when they are done you will eventually run out of memory - this is what is called a "memory leak".
So for you, calling free(...) correctly, is going to look something like this:
int **board = malloc(row * sizeof(*board));
for (int i = 0; i < r; i++) {
board[i] = malloc(col * sizeof(*board[i]));
}
// Do something with board
for (int i = 0; i < r; i++) {
free(board[i]);
}
free(board);

Want to Know About Different Scenario of Memory Leaks

I am just curious about how memory leaks happens when you write a C program.
Are the following are examples of memory leaks?
Trying to access the part of the memory whose access is not given to your program or when you are trying to access the location of the array which is not there.
#include <stdio.h>
int main(void)
{
int num[5];
int i;
for(i=0;i<5;i++)
scanf("%d", (num+i));
printf("%d\n", num[5]); //printing the data stored at loc num[5] which is not present.
return 0;
}
Printing the value stored in an un-initialized variables.
Use of void*memcpy(const*dst,void const*src,size_t n) function memory leak occurs when src and dst pointers points to the same memory address or function is undefined when addresses overlaps.
Use of free() more than once on the same pointers which has been freed already. For Example:
#include <stdio.h>
int main(void)
{
int*num = NULL;
int i;
num = (int*) calloc(sizeof(int), 5);
for (i = 0; i < 5; i++)
scanf("%d", (num + i));
free(num);
free(num);
return 0;
}
All of aforesaid scenarios cause undefined behavior.
printf("%d\n", num[5]); is out-of-bound memory access.
Printing the value stored in an un-initialized variables, in case of the variable has trap representation, causes UB.
Source and destination overlap in memcpy(), UB.
Multiple free() is also UB.
Also, memory leak is not about any invalid access, it is just wastage of memory leading to out of memory scenario for a system. You can read more about that here.

My code does not run for large values of n

This code runs for values of n of the order of 100k but when it gets to a million it stops and crashes.
#include <stdio.h>
int main()
{
int i;
long int n, sum;
n = 1000000;
int f[];
f[0] = 1;
f[1] = 2;
sum = 0;
for (i = 2; f[i-1] < n; i++)
{
f[i] = f[i-1] + f[i-2];
printf("%ld \n", f[i]);
if(f[i] % 2 == 0)
{
sum = sum + f[i];
}
}
printf("%d \n", sum);
getchar();
}
Yes, you cannot declare a very big local array because its sits in the call stack.
I'm sure your local variable int f[]; is a typo (that won't compile). You probably meant (after having set n) something like int f[n]; so you are using a VLA.
The call stack has a limited size (typically a couple of megabytes on current desktops running Linux).
You should allocate your big array in the heap (so use a pointer):
unsigned n = 1000000;
int *f = malloc(n*sizeof(int));
if (!f) { perror("malloc"); exit(EXIT_FAILURE); };
then you'll better clear it (because heap malloc-allocated memory zones contain garbage values):
memset(f, 0, n*sizeof(int));
then you can use it as you did.
At the end of your program (near end of main in your case) be sure to call free(p);; actually you should free a heap-allocated memory zone once you are sure to never use it. But beware (i.e. take care) of pointer aliasing!
Read about C dynamic memory allocation. Be scared of memory leaks and buffer overflows. Use valgrind if your system has it. Read also the wikipage on garbage collection. When you'll be more fluent with C programming, you might be interested in sometimes using Boehm conservative garbage collector for C.

Why does this array exist even after it is freed?

I am freeing the memory allocated to b. But I was under the impression that memory allocated dynamically disappears after you "free" it. But I am not getting any errors with this code and I can still access the original values assigned to elements of b even after freeing it. How is this possible ? What should I do to completely erase b ?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc,char* argv[])
{
int i, imax;
int *b;
imax=5;
b=malloc(sizeof(int)*imax);
for (i=0; i < imax; i++)
{
b[i]=i*i;
printf("%d ",b[i]);
}
free(b);
printf("\n memory freed \n");
for (i=0; i < imax; i++)
{
printf("%d ",b[i]);
}
printf("\n");
return 0;
}
result after compiling with gcc and running it
0 1 4 9 16
memory freed
0 1 4 9 16
This is an example of undefined behavior. There are many different possibilities, including:
The memory read is the exact same, because the C library just marked it as free without touching it
The memory read is garbage, because something else reused that newly-freed block
Your program crashes, because the address is no longer acceptable.
Your computer launches a nuclear missile headed for Antarctica, because hey, anything is possible with undefined behavior!
So please, for the sake of the cute little penguins, avoid reading freed memory!
Accessing an object after it has been free'd with free invokes undefined behavior. Don't do it.
That is:
for (i=0; i < imax; i++)
{
printf("%d ",b[i]); // invokes undefined behavior!
}
If you are unlucky nothing will happen but everything can happen from crash to nasal demons.

In C, memory allocating fails, why?

int x;
int komsuSayisi;//adjanceny matrix
int **arkadas;
int t;
int komsu[24][24];
scanf("%d",&t);
**arkadas = (int **)malloc( t*sizeof( int* )); //allocating rows
for(i=0; i<t; i++)
{
x=0;
arkadas[i] = (int *)malloc( t*sizeof(int) ); //allocating cow temporarily
for(j=0; j<t; j++)
{
komsu[i][j]=fark(kelime[i],kelime[j]); //fark returns 1 or 0.
//so i put those 1 ones to another matrix,arkadas
if(komsu[i][j]==1){
komsuSayisi++;
arkadas[i][x]=j;
x++;
}
arkadas[i] = (int *) realloc(arkadas[i], x);
//real allocating here
}
It gives error and shut downs.There is nothing wrong. What i want is adjanceny is too big to search so i will easily search the "1" ones with this matrix.
**arkadas = (int **)malloc( t*sizeof( int* ));
should be
arkadas = malloc( t*sizeof( int* ));
**arkadas dereferences an uninitialised pointer, resulting in you trying to write to an unpredictable address. You don't own the memory at this address so it isn't safe to try and write to it.
The second form assigns the address of an array of pointers to the local variable arkadas; this is what need to do.
Later in your program
if(komsu[i][j]==1){
komsuSayisi++;
arkadas[i][x]=j;
x++;
}
arkadas[i] = (int *) realloc(arkadas[i], x);
code inside the if condition attempts to write to arkadas[i] before you allocate it. This also invokes undefined behaviour and will likely crash. You can avoid the crash by removing the line arkadas[i][x]=j; and swapping your realloc call for malloc (you need the address of a previous allocation before you can call realloc)
if(komsu[i][j]==1){
komsuSayisi++;
x++;
}
arkadas[i] = malloc(x*sizeof(int));
I see
komsuSayisi++;
You didn't paste the whole code but probably thats what is crashing your program... I don't see any initializing previous to that increment....
this plus the deferentiation posted on the other answer

Resources