Why does this array exist even after it is freed? - c

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.

Related

malloc and pointer questions

We were shown this program in class yesterday and i have a question regarding it's output.
malloc.c:
#include <stdlib.h>
int *create_array(int);
int *create_array(int elements) {
int i,*x = (int *) malloc(elements*sizeof(int));
for(i=0;i < elements;i++) {
x[i] = i;
}
free(x);
return x;
}
int main(void) {
int j, *arr;
arr = create_array(5);
for(j=0;j<5;j++) {
printf("%d\n",arr[j]);
}
return 0;
}
Question(s):
When i run the program, i get this as output:
1627793032
1627793104
2
3
4
However, shouldn't the first 2 elements be 0 and 1 respectively? The values printed here seem like memory addresses to me, am i right? Also, is this due to some mistake causing undefined behavior?
After free(x);, the values pointed to by x are no longer valid. The memory can be reused for some other purpose, and meanwhile the memory allocation library can use the storage as it sees fit.
So, yes, it is a mistake resulting in undefined behaviour.
The real question is why do you even expect it to work? You free x, then you return a freed pointer which is nonsense.
What is happening is the following:
Inside the function you allocate 5 spaces, x points to the first
one's address.
You write 0, 1, 2, 3, 4 in these spaces.
You free x, so all the 5 spaces are not reserved anymore.
You exit the function, doing so the 2 next free memory spaces are
used, which happen to be the ones where you wrote 0 and 1.
You print the values contained in the 5 memory areas you've already
freed, where the ones in which you wrote 0 and 1 happen to have been
reused for something else; hence the weird numbers.
As a general rule, do not attempt to read areas of memory i've freed; even worse, do not try to WRITE there.
Accessing unallocated memory leads to undefined behaviour.
Also, you don't need to declare the function in a separate row if it's going to have nothing in between; plus you don't have to cast what's returned by malloc to the type; it's a void* that by default can hold anything you throw at it. What matters is your base variable type. See here
Corrected code:
#include <stdlib.h>
int *create_array(int elements) {
int i,*x = malloc(elements*sizeof(int));
for(i=0;i < elements;i++) {
x[i] = i;
}
return x;
}
int main(void) {
int j, *arr;
arr = create_array(5);
for(j=0;j<5;j++) {
printf("%d\n",arr[j]);
}
free(arr);
return 0;
}

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

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.

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.

What happens if you don't free dynamically allocated memory in a function?

I am learning how to write functions in C to accept an array and return a modified array.
In function testfunc (which is supposed to simply add 10 to each element of input array b) I am allocating memory for npts number of integers using malloc. But since I want to return this array using a pointer, I am not freeing this memory at the end of the function. Suppose I call this function 100 times like I am doing in the code, so what happens to the all the memory allocated during the code ? Is the amount of memory used by the code 100*10*4 bytes ? For a function which doesn't work on dynamic memory allocation, I think memory allocated to variables disappears when the function returns the final value and when it is called again, it again allocates memory and so on. But I am confused as to what happens in this case.
i cannot free the allocated memory inside the function since i need it to return the array to the main function, but also i need to call this function more than 100 times for different arrays, so if it keeps on allocating again and again, it will run out of memory
And is there a way to check how much memory a code is using ? (other than looking at Activity Monitor on Mac-OSX).
Thanks !
/* code to test returning array from functions */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int* testfunc(int *a,int npts);
int main(int argc, char* argv[])
{
int *b;
int a[10],i,j,npts=10;
b=(int *) malloc(sizeof(int)*npts);
for (j=0; j <100; j++)
{
printf("iteration number %d \n",j);
for (i=0; i<npts; i++)
{
a[i]=i;
printf("%d \n",a[i]);
}
b=testfunc(a,npts);
printf("returned array \n");
for (i=0; i<npts; i++)
{
printf("%d \n",b[i]);
}
}
printf("the size of one integer is %d \n",sizeof(int));
return 0;
}
int* testfunc(int *b,int npts)
{
int *c;
int i=0;
c=(int *) malloc(sizeof(int)*npts);
for (i=0; i<npts; i++)
{
c[i]=b[i]+10;
}
return c;
}
This is the possible solution to avoid allocating memory inside a function and being able to call the function multiple times
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void testfunc(int *c,int *d,int npts);
int main(int argc, char* argv[])
{
int *a,*b;
int i,j,npts=10;
a=malloc(sizeof(int)*npts);
b=malloc(sizeof(int)*npts);
for (j=0; j <100; j++)
{
printf("iteration number %d \n",j);
for (i=0; i<npts; i++)
{
a[i]=i;
printf("%d \n",a[i]);
}
testfunc(a,b,npts);
printf("returned array \n");
for (i=0; i<npts; i++)
{
printf("%d \n",b[i]);
}
}
printf("the size of one integer is %d \n",sizeof(int));
free(a);
free(b);
return 0;
}
void testfunc(int *c,int *d,int npts)
{
int i=0;
for (i=0; i<npts; i++)
{
d[i]=c[i]+10;
}
}
c=(int *) malloc(sizeof(int)*npts);
:
return c;
This passes back both the memory and the responsibility for managing it.
It has become the responsibility of the caller (main in this cae) to free it when finished.
Where your real problem lies is here in main:
b=(int *) malloc(sizeof(int)*npts);
:
for (some number of iterations)
b=testfunc(a,npts); // overwrites b
On that "overwrites" line, you actually have a memory leak because you lose access to the memory currently allocated for b (both originally and in the prior iteration of the loop).
And, as an aside, please don't cast the return value of malloc in C. It's not needed and can hide certain subtle errors that you really don't want to have to debug :-)
Since you are using malloc, which means you are allocating memory from heap not stack.
You should firstly figure out the mechanism of heap and stack.In C,malloc will help programmer allocate memory from heap, the same as new in C++.
So even if the function return the final value, the memory allocated will not be freed.If you call the function 100 times, it will allocate memory for you 100 times.
And as for a tool, you can refer to Valgrind, which is a powerful tool to check whether there exists a memory error.
It's main that have to free() the allocated space, but you have to be sure that you don't modified the value on the space during the function.
If dynamically allocated memory is not freed, it results in a memory leak and system will run out of memory. This can lead to program crashing.
hey objective of call by reference is to modify the input pointer and return back to caller.
means modified values i.e address still with caller.
You can simply do modification without allocate memory in your function
Just correction in your second approach
void testfunc(int *c,int npts)
{
int i=0;
for (i=0; i<npts; i++)
{
c[i] += 10; //YOU JUST INCREMENT VALUE by 10
}
}
My approach to write function:
no memory allocation
no multiple arguments
keep necessary input, output argument , return value
here int *c, npts -- input argument, output [ your value modified in int *c location]

valgrind (memcheck) tool didnot detect memory-leak

I introduced memory errors with following piece of C code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv){
int i;
int *a = (int *)malloc(sizeof(int) * 10);
if (!a) return -1; /*malloc failed*/
for (i = 0; i < 11; i++){
a[i] = i;
}
for (i = 0; i < 11; i++){
printf("a[%d] = %d\n",i ,a[i] );
}
// free(a);
return 0;
}
memcheck detects the errors Invalid read/write and definitely lost, which is correct and expected.
Now, I added the same piece of code to a shared object file(.so) of my application. This application runs as a service and is a daemon process. It never exits. I applied valgrind to my application and invoked the modified '.so' .
Memcheck detects Invalid read/write errors, but not definitely lost though all these errors are in one method.can i get some help in making memcheck detect memory leak (definitely lost) error?
Thanks in advance,
PV
How can valgrind know that you lost track of your allocated memory? It could see at the program end that the memory is not deallocated, but this is everything it can do for you. And if the program never exits, valgrind thinks you might still want to deallocate it later.
Even if valgrind would inspect all the variables and try to detect that no one points to the beginning of your allocated memory: it's perfectly legitimate to store the address in some modified form; for example, to the byte past the real beginning (think Pascal strings). So valgrind cannot detect if your code still knows about the allocated memory. Thus valgrind couldn't help you even this way.
To actually make valgrind detect the leak, you have to affect another value to a.
Try adding :
a = NULL;
after your for() loop.
Now valgrind should complain!
It won't tell you that you "irremediably lost" your memory unless you lose track of it.
I think that you mean
for (i = 0; i < 10; i++)
It would be preferable however to put a
#define N 10
or
const int N = 10;
at the beginning of your code, then to use the symbol N rather than the 10.

Resources