Adam
Adam

Reputation: 117

Understanding free() buffer before return statement

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

Answers (3)

Soundararajan
Soundararajan

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

  1. The space thus freed will be possibly used by the runtime in future calls of any dynamic memory allocation routines.

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

Weather Vane
Weather Vane

Reputation: 34575

After

free(buff);

any further operations which dereference buff are undefined behaviour.

Your function test() allocates a buffer, but then frees 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

eavidan
eavidan

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

Related Questions