[SOLVED]Dynamic memory allocation mystery

Thread Starter

Kittu20

Joined Oct 12, 2022
470
Hey Guys,

I wanted to allocate dynamic memory for multiple variables and assign values to memory locations.

I allocated memory for three variables, then allocated memory for two variables and then freed allocated memory.
C:
#include<stdio.h>
#include<stdlib.h>
 
int main ()
{
  // Memory allocate for 3 variables   
  int *var = malloc(3* sizeof(int));
  
  if ( var != NULL )
  {
    var[0] =  10;
    var[1] =  3;
    var[2] =  9;
  }
  
  // memory allocate for more two variables,
  //total memory allocated for five variables 
  var = realloc(var, 5 * sizeof(int)) ;
  
  if ( var != NULL )
  {
    var[3] = 9; 
    var[4] = 5;
    
    printf(" %d", *var);
  }
  
  free(var);
  
  printf(" %d", *var);
 
  return 0;
}
Output = 10 10

I don't understand why the value is stored even after the memory is freed ?
 

BobTPH

Joined Jun 5, 2013
8,935
It is, until it isn’t. There is no requirement to alter the memory when it is freed. But later, it might be allocated again and change unexpectedly. What did you expect your program yo do when you did that?

Use of the pointer after it is deallocated is a common program logic error call “dangling pointers.” These can be difficult to find and are a continuing problem with C and similar languages.

Other languages, like Java and Python do not allow explicit deallocation and do not have this problem.
 

Thread Starter

Kittu20

Joined Oct 12, 2022
470
What did you expect your program yo do when you did that?
I allocated dynamic memory first and assigned value there after that I freed the allocated memory.

I was expecting that after the memory is freed, the value stored in the memory should also be freed.

But from the program output you can see that the value of the variable was 10 when the memory was allocated and even after the memory was freed the value of the variable is 10
 

BobTPH

Joined Jun 5, 2013
8,935
Memory ALWAYS stores a value. Allocation and deallocation are merely a software convention on systems without virtual memory, like most microcontrollers.

This could be different on a system with virtual memory, such as X86 (PC). But even there, the deallocation would only happen on a larger page of memory, not at the level of your single int.

So what did you expect your program to do when you accessed freed memory? Did you expect it to print nothing? Crash? Print 0? Why?
 

WBahn

Joined Mar 31, 2012
30,034
I allocated dynamic memory first and assigned value there after that I freed the allocated memory.

I was expecting that after the memory is freed, the value stored in the memory should also be freed.

But from the program output you can see that the value of the variable was 10 when the memory was allocated and even after the memory was freed the value of the variable is 10
What does it mean to "free a value"?

Memory that is freed is merely available to be allocated again in a future call to malloc. You need to understand how memory allocation (and reallocation) work. Perhaps a physical analogy might help.

Imagine you have a hundred index cards laid out in front of you. Each card is assigned a permanent index number (this is the card's address) and on that card can be written a single number, but that number can be changed (this is the card's contents).

Let's walk through your program using this index-card memory.

You first call malloc() and ask for a block of three consecutive index cards. The memory manager looks at some things and says, "Your requested block starts at card 37." It also makes a note that a block of memory consisting of 3 cards starting at card (36) is not available (i.e., isn't 'free').

You then write 37 on your card that you are calling 'var'.

Now you execute
var[0] = 10;

This means to compute the address by taking the value of var (37) and adding an offset of (0) to it, yielding address 37, and writing 10 on that card. That value of 10 is going to stay on that card until it gets overwritten by a different value.

Similarly, the value 3 and 9 get written on cards (38) and (39), respectively.

Now you call

var = realloc(var, 5 * sizeof(int)) ;

What the memory manager will do is determine if the additional two index cards, (40) and (41), are available (i.e., 'free'). If they are, then the memory manager merely updates the information it is tracking so that it now knows that the block of memory starting at index (37) is now 5 cards long and it returns the same index, (37) in this case.

However, if (40) and/or (41) are not available, then the memory manager will find a new block of free memory that is big enough. Let's say that that starts at card (73). It will then copy the contents of the three-card block at location (37) and return the index of the new block (73), which you store in your 'var' variable. It also updates its records to make note of the fact that cards (37) through (39) are now available for future use (this is all the 'free' means).

Notice that, in either case, the value at var[0] is going to be 10, but the card that gets referenced is either the original card at (37) or the new card at (73).

Also notice that, in either case, the value written on card (37) is still going to be 10, even if that block was freed.

Now you explicitly free 'var'. ALL that happens is the memory manager makes a note that those five cards are available for reuse. It does NOT change the values written on those cards. Also, you still have the card number of the first card in the block written on your 'var' card, so you can still access it and print out the value currently stored there. You can also write to it and change it -- and that will work just fine. In fact, there's a very good chance that your program will work fine for a long time. But, eventually, the program is going to run in such a way that when you call malloc() (or realloc() or any other function that allocates memory) that it will return a block of memory that includes one or more of those cards and when that other code writes to it, it overwrites what you had written there. That's a bad thing -- and it's a hard thing to find precisely because the program might literally work just fine over and over for years before that situation arises.

This is why it is good practice to always set a pointer to NULL immediately after freeing it. That way, if you try to use it to access memory that's been freed, your program will (hopefully) crash, or at least misbehave in such a way that the fact that something isn't right will be readily apparent.
 
Top