3

Given two functions, func1 and f2, with the following signatures:

void func1(){
    int baba = 12345;
    // printf the value of baba here
}

void f2(){
    int loo;
    //printf the value of loo here
}

...if I run my int main, which only has func1 then f2:

int main(){
      func1();
      f2();
}

...then the printed value of both baba and loo will be 12345. So my question is as follows:

  1. Is this defined behaviour, or just something erroneous that my machine does?

  2. If this isn't some erroneous thing my computer did, can you explain why the compiler chooses to store loo in the same address as baba?

EDIT: I guess I should ask, if I have these EXACT two functions, will baba and loo have the same value on ANY machine?

I understand loo's value is the result of baba's leftover bits, and I understand that (on my machine, at least) the stacks of both are being laid out such that loo overlaps onto baba's old territory. Is it true that every machine would lay these two function stacks out in such a manner that baba and loo overlap? Using these two functions exactly as written, that is...

user207421
  • 305,947
  • 44
  • 307
  • 483
touch my body
  • 1,634
  • 22
  • 36
  • 2
    Think about how temporary local variables can be allocated on the stack and then it should be obvious. – Paul R Dec 09 '14 at 23:19
  • 4
    1. Its UB. 2. Its an erroneous thing in the code, not the compiler. `loo` is indeterminate. Evaluating it invokes UB. Why the same address choice was used is implementation-dependent. – WhozCraig Dec 09 '14 at 23:19
  • If an interrupt happens between calling `func1()` and `f2()` the previous `12345` on the (below stack pointer) stack would not survive. – Weather Vane Dec 09 '14 at 23:24
  • I think that this is undefined behaviour. The way that it works is that when you call func1 the stack is pushed and the value 12345 is put assigned to an address in the new stack frame. When you leave func1 the stack is popped back to the calling stack frame. When you call f2 the stack is again pushed and as you have the same number of parameters in both calls (none) the location in memory of loo is now where baba was, this bit of memory has not been wiped and contains the same data. – Matthew V Carey Dec 09 '14 at 23:26
  • @PaulR can you explain? I don't know much assembly so maybe I'm missing something.I know that during the creation/destruction of func1(), the space assigned to baba gets the int literal "12345" written into it. When loo is created, it's taking that same address space. I understand that's why the value is there, but I was wondering if it's merely coincidence that loo has the same address space. I guess a better question would be, is loo guaranteed to always occupy that space (in THESE given functions, on every platform) – touch my body Dec 09 '14 at 23:29
  • Thank you all very much for the insight!!! – touch my body Dec 09 '14 at 23:31
  • 1
    I am puzzled why this question is marked as answered and linked to a different question. If it has been answered, it should be to a similar question. – user3344003 Dec 10 '14 at 04:03
  • @user3344003 Yeah, I was wondering the same. These are two very different questions, as mines about assembly and portability, whereas the linked one is about stacks and scope – touch my body Dec 10 '14 at 20:37

1 Answers1

11

In f2(), lolo is uninitialized. It's content is hence undefined.

Most often however, the content appears to be the data that was on the stack. By coincidence, you've first called func1(), which has exactly the same memory/stack layout than f2(). So by chance the variable contains the data that was previously stored at the same place.

This behavior is not guaranteed at all. It only appears to work in this specific context because no other local variables were created between the two calls, and no other function call overwrites the data with other content (and the two functions have exactly the same memory layout).

Here a small picture to explain the situation in this specific case: enter image description here

Christophe
  • 68,716
  • 7
  • 72
  • 138
  • 3
    I use "undefined" as in "Undefined Behaviour" i.e. the c++ standard does not define a behaviour. But undefined/indeterminate does not mean that it's random. So I dare to maintain: *"It works only in this specific case on this compiler with the same compiling switches with this operating system"* – Christophe Dec 10 '14 at 00:00