5

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;
}
Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
Stack
  • 235
  • 3
  • 15
  • what is `c` here? `int c`? – Sourav Ghosh Jan 15 '15 at 12:33
  • I think it has to be for performance, the memory is deallocated not zeroed, why would it be zeroed? is anyone interested in it being zeroes? it's just made available if you need to reuse it, why dont you try with the same function but passing another variables address to it, it might overwrite the old one, the `Hello()` function is smaller that the `Add()` function. – Iharob Al Asimi Jan 15 '15 at 12:35
  • Yes it should be int c and Add. I edited that part.. – Stack Jan 15 '15 at 12:41
  • "*Is it because like in heap we need to assign a pointer to null after freeing it or else we can still access it?*" Changing the value stored in a pointer has no effect whatsoever on whether you can or can't still access the object it points/pointed to. – David Schwartz Aug 27 '19 at 06:58

5 Answers5

8

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.

Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
  • U said when a function returns it leaves the stack area unchanged but if we have another function shouldn't the add function be deallocated because we follow LIFO here so after the Hello function, main function should be active but if we have the add function in the call stack then by LIFO principle how can it reach main? – Stack Jan 15 '15 at 12:51
  • @Stack Added some details, hope this is useful. – Mohit Jain Jan 15 '15 at 13:00
  • 2
    @MohitJain sir, best possible explanation. +1. :-) – Sourav Ghosh Jan 15 '15 at 14:04
1

TL;DR answer, it is undefined behaviour. You cannot reasonify any output of the above execution. Don't be surprised if it ends up printing your mobile phone number or ZIP code. :-)

After the scope has expired, what happens to the stack location, is environment dependent. If not required, the stack space allocated for c might not get reused and hence you're seeing the assumed proper output, but still it is undefined. Someday, in a different environment, you may see a different answer.

Mr. Mothit Jain's answer gives a very detailed explanation of this.

Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
1

To fully understand this I recommend you to learn assembly for your processor and see how your code gets compiled. At this point I think could help if I say that returning from function does not call any memory freeing function, it merely adjusts registers and since between Add and print you didn't do anything that would change the value on the "deallocated" stack, you get the number. Try calling a function that returns.. pfft i dunno 77 in between (but do save it to local variable!) and you will print a different result. Learn the assembly though, be a proper programmer.

Pyjong
  • 3,095
  • 4
  • 32
  • 50
  • But i included a function Hello before the printf,so shouldn't the add function be deallocated so as in the stack we have Hello and then main and LIFO is maintained? – Stack Jan 15 '15 at 12:55
  • You can now see why that is from Mohit's answer. Your hello function just does not reach the address. Actually so doesn't seem Mohit's version, I wouldn't think, but would you take the Add function and just changed the name to Hello and made c = 42 then even if you returned 0 or whatever you would get 42 in your print – Pyjong Jan 15 '15 at 13:48
0

The Hello function does not put anything new on the stack, as it has no auto-variables. Consequently the memory location that was previously occupied by c is still unchanged. Change Hello so that it modifies the memory and you'll change the value at p.

void Hello(void)
{
    //This will overwrite the memory previously containing '5' with '3`, the number
    //of characters output by the printf() function.
    int grub = printf("Yay");
}
Evil Dog Pie
  • 2,300
  • 2
  • 23
  • 46
0

I think it is because that you did not define "stack variable" in Hello function, when I run the below program:

#include <stdio.h>

void Hello()
{
  int tt = 100;
  int tt1 = 5000;
  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;
}

It prints 5000 in my Linux And 1 in my Mac, Anyway I think they are both unexpected value.

vmcloud
  • 650
  • 4
  • 13