0

This is my code

#include<iostream>
using namespace std;
int *ptr;
void hold(){
  int a=12;
  ptr=&a;
};

int main(){
  hold();
  cout<<"value of a="<<*ptr;
};

and I get value of a=12 This must not happen because compiler has freed the value at address of a so why 12 comes?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Sachin Setiya
  • 273
  • 1
  • 3
  • 13
  • 1
    "12 comes" because you're lucky -- freed memory does not mean it's reused or overwritten right away, just that you have little or no control of when that will happen. This is what makes the behavior "undefined". – mah Mar 10 '14 at 11:48
  • Well what did you expect to get? – Simple Mar 10 '14 at 11:48
  • "This must not happen" - why not? Undefined behaviour means that anything could happen, including memory retaining its value after use. – Mike Seymour Mar 10 '14 at 11:50
  • to @mah i have tried many times but always i get same value of as that of a – Sachin Setiya Mar 10 '14 at 11:51
  • 1
    possible duplicate of [Can a local variable's memory be accessed outside its scope?](http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – Engineer2021 Mar 10 '14 at 11:56
  • 1
    @SachinSetiya: That's because your program doesn't do anything between returning from the function and reading the dead memory; nothing has reused the memory and changed its contents. You might see a different result if you call another function and set local variables there. Or you might not - you can't assume anything about undefined behaviour. – Mike Seymour Mar 10 '14 at 12:12

6 Answers6

6

This is undefined behavior.

You can get any value, or a crash, or anything at all.

Since "exactly what I expected" is part of "undefined behavior", you cannot reason about it like "it did what I expected, therefore it's not undefined but works perfectly". That line of reasoning is invalid.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • i always get same value as that of a this may not be the undefined behavior – Sachin Setiya Mar 10 '14 at 11:54
  • undefined behavior doesn't mean that the behavior won't repeat in the future – phuclv Mar 10 '14 at 11:55
  • 1
    @user2977406: Undefined behavior does not mean random behavior. It just means "undefined within the terms of the C language standard". When you look at a specific implementation and runtime environment you will be perfectly able to tell which behavior you'll observe consistently. But what happens exactly does depend on the particular compiler, operating system and libraries you use. – datenwolf Mar 10 '14 at 11:59
3

Freeing doesn't mean that the system will modify the value stored there (which would involve unnecessary overhead). It just means that this memory space is made available for future storage.

1

Because you're invoking undefined behavior. Anything can happen when you do what you did.

A bit more elaboration: Variables defined within the local scope without being `static' reside in an area, that the C specification only vaguely calls "automatic memory". As soon as the scope of the function is left, all the contents in the automatic memory of that function invocation are no longer defined. To make this clear: Automatic memory is not associated with the function it's associated with a specific call of the function.

The practical method in which automatic memory allocation/deallocation is done is implementation-defined. But there is a de-facto standard way to implement automatic memory, which is called stack frames.

The stack is a designated ares of memory where with each function call another chunk of that memory area on top of the existing stack is allocated for the scope of the function call. So for each function call in the chain of function calls in the program another hunk of automatic memory area is put on top of the previously allocated areas, i.e. it forms a stack of automatic memory areas. When a function scope is left – and that can happen only for the last function in the chain of function calls – the whereabouts of the associated stack frame are simply discarded. But the contents of what got stored there are not destroyed in the usual implementations. Which means, that, as long as no other function got called you will find the junk left behind, if you know where to look.

So in a stack frame based implementation, that does no cleanup on scope exit, taking the address of a variable in automatic memory and passing it up to higher scopes does just that and may present you with contents of a no longer valid scope. But implementations may as validly choose to mark the unused parts of stack memory as invalid with the OS and trying to access it may crash the program as well.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
1

a is freed once the function returns (since it is visible only in the function's body scope) so your ptr pointer points to an un-allocated memory address. Since freeing does not delete the value at that address (just marks the address as free) the value 12 might still be shown when accessing ptr at that address.

giorashc
  • 13,691
  • 3
  • 35
  • 71
1

The address of a local variable in a function depends on the state of the stack (the value of the SP register) at the point in execution when the function is called.

So a local variable may have a different address each time the function is called, and you cannot rely on the contents of that address once you're outside the function.

barak manos
  • 29,648
  • 10
  • 62
  • 114
0

I know your question is already answered quite well, but if you're interested in getting an understanding of what is happening under the covers. Just so you get a slightly clearer understanding of why and how this stuff works, try this:

#include <iostream>

using namespace std;
int *ptr;
void hold(){
  int a=12;
  ptr=&a;
};
void func() {
  b = 3444;
}

int main(){
  hold();
  func();
  cout<<"value of a="<<*ptr;
};

You will probably find a very different value printed out. What is happening behind the scenes as was alluded to by barak is that the values for a and b are allocated on the stack. When the function returns, the variable is "freed". It's actually not so much freed as the stack pointer is changed. On the subsequent call to func() another stack frame is simply placed on the stack. This other stack frame has very similar contents to the stack frame for hold() so chances are that the location for b will be the same as the location for a. Again, I say chances are because an implementation is not required to lay the stack out that way.

The gist of it is that as you allocate things on the stack, it stays there until something new comes on top of it (another stack frame).