-2

Lets say this is the snapshot I want to talk about. In this code, main function calls 'foo' which returns address of locally declared variable 'a'. I was under the impression that locally declared variables de-allocates the memory when they go out of scope. Variable 'a' should be de-allocated after call to foo is done and there should not be anything left related to 'a'. But in this case, it seems to be breaking that basic assumption. What is going on underneath?

int* foo() {
  int a = 5;
  return &a;
}

int main() {
  int* p = foo();
  // Prints 5
  std::cout << "Coming from foo = " << *p << std::endl;
  *p = 8;
  // Prints 8
  std::cout << "Setting explicitly = " << *p << std::endl;
}
Hemant Bhargava
  • 3,251
  • 4
  • 24
  • 45
  • 1
    It's undefined behavior. Don't count on any predictable behavior of such programs. – R Sahu Oct 07 '16 at 06:11
  • @RSahu. I understand that it is undefined behavior. My suspicion arises more when I tried to compile this with different machines(many times). – Hemant Bhargava Oct 07 '16 at 06:13
  • The entire stack frame isn't necessarily overwritten straight away, but it could be depending on your compiler, and the amount of stack space, the OS etc... – George Oct 07 '16 at 06:14
  • 1
    UB is UB. _It works as intended_ is part of the UBs set from which to pick up. – skypjack Oct 07 '16 at 06:19
  • Try calling another function and then print the value again... – Peter - Reinstate Monica Oct 07 '16 at 06:19
  • What does "de-allocate the memory" do, according to you? – CompuChip Oct 07 '16 at 06:23
  • @CompuChip, The memory becomes available for reuse. – Hemant Bhargava Oct 07 '16 at 06:25
  • @PeterA.Schneider, You are right. If I write `int* p = foo(); std::cout << "Coming from foo = " << *p << std::endl; std::cout << "Setting explicitly = " << *p << std::endl;`, then also I see garbage value in second statement. – Hemant Bhargava Oct 07 '16 at 06:26
  • 1
    Re: " The memory becomes available for reuse.": More precisely, it becomes available for re-allocation. One could argue that it is available for re-use as long as it's allocated ;-). – Peter - Reinstate Monica Oct 07 '16 at 06:28
  • 1
    @Hemant Bhargava: Yes, but that does not mean that it somehow gets sanitized, burned with fire or rinsed with chlorine solution. The memory is still there and whatever "garbage" you left behind in it is still there, stored in that memory. Your "garbage" will normally remain there until the memory actually gets reused and the new owner cleans it up and reuses it for their own purposes. In your case you just keep peeking into that "available to reuse" memory and keep seeing that nobody yet cleaned up what you left behind. – AnT stands with Russia Oct 07 '16 at 06:28
  • @AnT For some reason, on Coliru and on my cygwin/64 bit gcc it dumps core with a seg fault. This indicates that something else is happening besides resetting the stack pointer, like invalidating a page of memory. – Peter - Reinstate Monica Oct 07 '16 at 06:30
  • @Peter A. Schneider: That could happen too. Happened to end up on page boundary or something like that. – AnT stands with Russia Oct 07 '16 at 06:36

2 Answers2

4

Your code invokes undefined behavior. As aptly as it is named, it is not defined, meaning you may get the expected result or you may not. What you should do is not rely on such results since they are not well-defined. You may feel lucky for getting expected results, but believe me, it's a trap!

Mike Precup
  • 4,148
  • 21
  • 41
CinCout
  • 9,486
  • 12
  • 49
  • 67
  • I understand that it is undefined behavior. But why I got the same value was the question. I think below answer wrote that. – Hemant Bhargava Oct 07 '16 at 06:28
  • 2
    @HemantBhargava it seems you don't understand that "undefined behaviour" means you may see the same value – M.M Oct 07 '16 at 06:34
  • @M.M, I see that value coming as '5' when I compiled this code on different machines. That is why my suspicion increased. – Hemant Bhargava Oct 07 '16 at 06:58
  • "...you may get the expected result or you may not." You were just lucky to get the expected result every time. Go buy a lottery ticket today ;) – CinCout Oct 07 '16 at 09:01
0

It depends on your machine/compiler what value is printed. The deallocation of stack doesn't mean what was there earlier got erased. It just means that area has become invalid. That means the behavior is not guaranteed when you try to access those addresses. In your case, it just happens that the location used for storing the local variable a has not been overwritten.

nishantsingh
  • 4,537
  • 5
  • 25
  • 51
  • This is what I wanted to hear. Thanks! – Hemant Bhargava Oct 07 '16 at 06:27
  • The comments and answers have already tried to drive the point home that undefined behavior is undefined and _anything_ could happen, and I would like to stress this again, but many systems will actually show you the same output when running the code above. If you want to understand why, you should look into a thing called the stack pointer. Basically, the stack of the application (that you allocate variables like `int a = 8` onto) is a continuous block of memory that can grow and shrink from one side. To keep track of how big it is, a special pointer is kept which is called [.. ctd] – CompuChip Oct 17 '16 at 06:19
  • [ctd] the Stack Pointer and points at the "top" of the stack, it's basically a separator of the allocated and the unallocated memory. If you allocate stack memory by writing `int x;` you basically shift the stack pointer one position into the unallocated area (and note that if you don't assign `x` a value, `x` will have the value of whatever was there). The quickest way to deallocate the memory, like when `a` goes out of scope in your code, is just shifting the SP back. (Beginning) programmers often expect the memory to also become zero, or something like that, but that is an expensive [..ctd] – CompuChip Oct 17 '16 at 06:19
  • [ctd] operation to write to memory that nobody should be using anymore anyway: if it is deallocated nobody should read from it, and if it ever gets reallocated the first action should be to write somthing to it. – CompuChip Oct 17 '16 at 06:20