-3

i cannot understand why the value of *p and *p1 change after cout their value in the code lines below. thank you for your help.

void g(int *&x) {
    int a = 3;
    x = &a;
}
void h(const int *&x) {
    int b = 2;
    x = &b;
}

int main() {
    int *p = new int;
    *p = 5;

    g(p);
    cout << p << " " << *p << endl; // 0095FD48 3 *why the value change in the next line? *
    cout << p << " " << *p << endl; // 0095FD48 1829755776 
    const int*p1 = p;
    h(p1);
    cout << p << " " << *p << endl; // 0095FD48 2 *in here it happen, too*
    cout << p << " " << *p << endl; // 0095FD48 1829755776 
}
  • 3
    Both functions `g()` and `h()` expose _undefined behavior_. – user0042 Oct 01 '17 at 19:13
  • 2
    Possible duplicate of [Can a local variable's memory be accessed outside its scope?](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – user0042 Oct 01 '17 at 19:14

1 Answers1

3

g() and h() assign the address of a local variable to the parameter and thereby expose the address to the caller. When these functions return, the local variable is freed, i.e., its place on the stack may be re-used.

Therefore, this is undefined behavior. In your example, it is a case of "use after free".

The calls to cout and its operator<< use some portion of the stack and overwrite the "former local variable".

There are several fixes for your sample code, depending on what you want to achieve:

  1. If you want your function to modify the value of *p of the main function, then do not introduce a new integer variable in g(), but access the existing one: void g(int *&x) { *x=3; }

  2. Is basically the same as (1), but you without references instead of pointers. void g(int &x) { x=3; // x is no local variable but references the callers argument }

  3. Allocate a new variable. void g(int *&x) { x = new int; // allocate int value on heap *x = 3; } Because you pass a pointer as reference, the former pointer value will be overwritten, which may lead to a memory leak.
  4. Same as (3) but using a return value and thereby reducing the risk of memory leaks: int * g() { int *x = new int; // allocate int value on heap *x = 3; return x; }

  5. To avoid memory leaks, you may use "automatic pointers", see http://www.cplusplus.com/reference/memory/unique_ptr/

Black
  • 5,022
  • 2
  • 22
  • 37
  • Your answer is very useful, thank you a lot. However there are something which i still confused. Can you explain for me? what do u mean when said "thereby expose the address to the caller" and "use some portion of the stack and overwrite the "former local variable"." – Hoang Nguyen Oct 01 '17 at 19:34
  • @HoangNguyen -- The concept is simple. You are storing the address of a *local* variable. When `g()` or `h()` returns, that local variable no longer exists. So what are you pointing to after the function returns since that variable has vanished? – PaulMcKenzie Oct 01 '17 at 19:39
  • @ PaulMcKenzie i understood what u mean but i confused that why it still cout the value of *p=3 in the first line and it change right after in the next line. it mean that local variable was vanished after the first line of cout right ? – Hoang Nguyen Oct 01 '17 at 20:06
  • 1
    No, it vanished before that - you just got lucky and saw what you expected to see. For example, if you call another function after calling 'g', and before using cout, you'll probably find the value changed in the first line too. – IanM_Matrix1 Oct 01 '17 at 20:14
  • The value doesn't actually vanish from memory. The value was stored with automatic storage duration and so was probably stored on the stack. During the first call that part of the stack it was stored at was not yet overwritten. But `std::cout` probably uses the same part of the stack that became available, and so by the time the second one is called the value was indeed overwritten with something else. All of this is speculation however as the compiler is free to allocate new variables as it sees fit and this behavior is undefined, so we can't refer to the C++ standard to know. – wally Oct 01 '17 at 20:14
  • I'm talking variables, you are talking memory. As soon as the function 'g' returns, the variable no longer exists, so he's got a dangling pointer that he's now dereferencing. – IanM_Matrix1 Oct 01 '17 at 20:28
  • 1
    @HoangNguyen -- The local variable has a lifetime, that life has ended when the function returns, and thus that address is free for use by compiler. By outputting the value, you're just playing games with an address that no longer can be used in a defined manner by your program, plain and simple. Therefore the behavior of your program is undefined. – PaulMcKenzie Oct 02 '17 at 01:27
  • So are there any method to return local variable after function call ? I hear that we should create dynamic variable so that it will be stored in heap but i confused that does it be free after function returned (i mean if we didnt call delete operator )? thank you all. – Hoang Nguyen Oct 02 '17 at 19:29
  • @HoangNguyen Strictly speaking, there is no safe way to return a pointer to a local variable (because that variable would no longer be local). I will edit my answer to provide some ways how to return pointers in a safe way. – Black Oct 05 '17 at 04:31