Search code examples
c++cpointersmemory-managementdangling-pointer

Memory allocation stack


In the stack, memory is reserved for main which we call stack frame for the main function.

When we call the Add function, memory is reserved on top of the stack. In the Add function stack frame, a and b are local pointers and c is an integer which calculates the sum and then we return the reference. c is a local variable of Add function.

Now when the Add function execution is completed the memory space in the stack is also deallocated so when we try to access this address in the main with pointer p, what we are trying to access is basically a deallocated space. The compiler gives a warning but why does it still print the value 5 correctly?

The answer to that may be that the machine didn't deallocate the memory space as it didn't deem it necessary as there were not any more functions. But if we write another function Hello then it should definitely deallocate the space for Add function in the call stack but the program still prints

Yay     5

Is it because like in heap we need to assign a pointer to null after freeing it or else we can still access it? Is something like that related here?

/* void Hello()
   {
     printf("Yay");
   } */

int* Add(int *a,int *b)
{
  int c=*a+*b;
  return &c;
}

int main()
{
  int a=1,b=4;
  int *p=Add(&a,&b);
  // Hello();
  printf("\t%d",*p);
  return 0;
}

Solution

  • Assuming c is local int variable, accessing c after function call is undefined-behavior and may print expected result, or may do something unexpected.

    Though C doesn't mandate, but typically it is implemented using stack. For performance reasons, when a function returns, it leaves the stack area unchanged. That is the reason why you are seeing the value 5 i.e. 1+4. But you should never count on this.


    When you use the second function, behavior still remains undefined so you can get any output. In practice if you define another variable in second function and use it, the output may change.

                           +-----------------+
                           .(local variables).
                           |'''''''''''''''''|
                           |                 |
    +----------------+     . PRINTF FUNCTION .
    |  c = 42        |     |                 |
    |''''''''''''''''|     +-----------------+
    |                |     |                 |
    .  ADD FUNCTION  .     . HELLO  FUNCTION .
    |                |     |                 |
    +----------------+     +-----------------+
    |  b = 4         |     |  b = 4          |
    |''''''''''''''''|     |'''''''''''''''''|
    |  a = 1         |     |  a = 1          |
    |''''''''''''''''|     |'''''''''''''''''|
    |                |     |                 |
    .  MAIN FUNCTION .     .  MAIN  FUNCTION .
    |                |     |                 |
    +----------------+     +-----------------+
    

    In above diagram, I tried to visually represent how the stack might stack look when you are inside Add function and Hello function. You can see that Hello is not messing up with the stack memory that was reserved for c in Add function.

    You can verify this by rewriting the Hello function as

    void Hello()
    {
      int i = 42;
      printf("Yay - %d\n", i);
    }
    

    May print 42 in main.