doubleE
doubleE

Reputation: 1073

Call stack is reused between 2 function calls

Following simple C program outputs 42 to my surprise. I expected it to output a garbage value or 0, since stack frames are different for foo() and bar(). How the output is deterministic to be 42 ?

#include <stdio.h>
void foo(void){
    int a;
    printf("%d\n",a);
}

void bar(){
    int a=42;
}

int main(){
    bar();
    foo();
    return 0;
}

>>gcc -o test test.c

>>./test

42

When I instruct compiler to optimize the code, it prints garbage!

>>gcc -O -o test test.c

>>./test

2487239847

Upvotes: 1

Views: 86

Answers (2)

sreepurna
sreepurna

Reputation: 1666

Yes, the value 42 is a garbage. Here is the explanation for it:

Every function in stack, starts similar to this order

  1. Parameters of the function
  2. Return value of the function
  3. EBP( Which stores previous frame pointer)
  4. Exception handler frame
  5. Local variables
  6. Buffer
  7. callee save register

In the above example, main() is called and follows the procedure as above.

Then it encounters the bar() follows 1,2,3,4 steps mentioned and then stores the local variable a=42 in the memory(5) then 6,7 are followed then it will come out of the memory.

Then it encounters the foo() follows 1,2,3,4 steps as same in the memory location that bar() had. And you declared a local variable called a which will point to same memory location that bar() holding the local variable a=42. So it is giving the same value 42 when you are printing, which is actually a garbage value.

To validate this, try this example: This prints 7

#include <stdio.h>
#include <string.h>

void foo() {
    int b;
    printf("%d\n",b);
}

void zoo() {
  int dummy = 7;
}
void bar(){
    int a1=3;
}

int main(){
    bar();
    zoo();
    foo();
    return 0;
}

Ref: Doc

Upvotes: 2

Aniruddh Dikhit
Aniruddh Dikhit

Reputation: 682

The function calls go on stack (their activation records), in this case the two functions foo and bar are identical in terms of parameters, return type and the local variables within each function. So the first call puts something on the stack and once done its activation record is popped out but not cleaned (compiler does not generate code to clean things up). Now the second function call essentially ends up using the same memory location and therefore gets the value from a previous call using same memory area. The values that are not initialized in a function are considered undefined. In the foo and bar case we got to the same value due to similar signature of two functions and same type and location of the variable. Try adding two integers or integer and a float in one function and reverse the order in next and you'll see the effects. Of course when you call the optimizer it might place things on register and as a result you may get undefined values when the compiler sees no scope for optimization as in case of foo.

Upvotes: 1

Related Questions