Reputation: 117
I want to understand the behavior of returning a pointer from a function call. Suppose I have the following simple code:
int main(){
int i;
float *ssd;
ssd = test();
for (i = 0; i < 3; ++i) {
printf("%f, ", ssd[i]);
}
printf("\n \n");
memset(ssd, 0.0, 3*sizeof(float));
for (i = 0; i < 3; ++i) {
printf("%f, ", ssd[i]);
}
printf("\n \n");
}
float *test(){
float *buff = malloc(3* sizeof(float));
int i;
for (i = 0; i < 3; ++i) {
buff[i] = (float) (6.31 + i);
}
free(buff);
return buff;
}
As you see, I created a temporary buffer buff
inside test()
. Before I return, I freed buff
before return
statement. Although I tested it and the results were as expected, I don't understand how test()
function could return buff
values even though free(buff)
is before return
buff?
Upvotes: 0
Views: 7346
Reputation: 2194
From libc documentation,
Occasionally, free can actually return memory to the operating system and make the process smaller. Usually, all it can do is allow a later call to malloc to reuse the space. In the meantime, the space remains in your program as part of a free-list used internally by malloc.
A call to free doesn't guarantee, that the space is cleaned up. But what is guaranteed (at least by the GNU libc implementation) is that
To prove this i modified your program as follows. It basically adds a for loop in your test() function which just allocates and free's the buff for n times (e.x. 10 times) and prints the contents of the buffer in course. So everytime i run the program, it prints the contents for the first time and when malloc() and free() is called the contents of *buff are cleared and garbage is printed. (tested on a mac, gcc 4.8+). Hope this helps.
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
float *test(){
float *buff = malloc(3* sizeof(float));
int i, j;
for (i = 0; i < 3; ++i) {
buff[i] = (float) (6.31 + i);
}
free(buff);
int n = 10;
for(i=0;i<n;i++)
{
printf("Iteration %d ", i);
for (j = 0; j < 3; ++j) {
printf("%f, ", buff[i]);
}
printf("\n");
buff = malloc(3 * sizeof(float));
free(buff);
}
return buff;
}
int main(){
int i;
float *ssd;
ssd = test();
printf("\n \n");
memset(ssd, 0.0, 3*sizeof(float));
for (i = 0; i < 3; ++i) {
printf("%f, ", ssd[i]);
}
printf("\n \n");
}
Upvotes: 0
Reputation: 34575
After
free(buff);
any further operations which dereference buff
are undefined behaviour.
Your function test()
allocates a buffer, but then free
s it before returning it to main
, as ssd
.
So when ssd
is dereferenced in main
, although the pointer still has the same value it was allocated by malloc
, it is no longer pointing to memory that you "own". So from then on, anything can happen. Your code may still work, or it may not.
Upvotes: 5
Reputation: 5564
The memory pointed at originally by buff
is not overwritten, thus retaining the values you stored in it.
This is usually what we call "memory containing garbage", but since you initialized it then everything is working.
Upvotes: 0