The Tricky C exercise deals with pointers. Need help understanding solution

Consider the following code:

int *foo (int x) {
int a[2];
a[0] = x;
a[1] = x + 1;
return a;
}
…
int *p1 = foo(2);
int *p2 = foo(3);

      

To conclude this piece of code, what are the meanings of each of the following? (answered)

 p1[0] = 3
 p1[1] = 4
 p2[0] = 3
 p2[1] = 4

      

Since a is allocated on the stack, the memory does not remain allocated when the call returns and can be reused by something else. In this case, since foo (3) is called immediately after foo (2) at the same call depth (i.e. it uses the same stack space), they both return the same pointer, i.e. p1 is equal to p.

I didn't understand this explanation. What does this actually mean? Why do we have the same values ​​for p2 and p1? I know that you cannot return a pointer to a local variable in C .. but I don't understand why p2 and p1 have the same values ​​....

+3


source to share


5 answers


Using a pointer to automatic storage variables (function-limited variables) outside of its scope is undefined, which is why you should never do this and will never depend on its behavior.

However, if you want to strip the cover on the compiler / machine / os, the reason is that the automatic storage is allocated at the same address for the two function calls.

Example...

#include "stdio.h"

int* foo(int x) {
  int a[2];

  printf("&a[0] = %p\n", &a[0]);
  printf("&a[1] = %p\n\n", &a[1]);

  a[0] = x;
  a[1] = x + 1;

  return a;
}

int main(int argc, char* argv[]) {

  printf("foo(2)\n");
  int* p1 = foo(2);

  printf("foo(3)\n");
  int* p2 = foo(3);

  printf("p1[0] = %i\n", p1[0]);
  printf("p1[1] = %i\n\n", p1[1]);

  printf("p2[0] = %i\n", p2[0]);
  printf("p2[1] = %i\n", p2[1]);

  return 0;
}

      



outputs ...

foo(2)
&a[0] = 0x7fff4dd0f054
&a[1] = 0x7fff4dd0f058

foo(3)
&a[0] = 0x7fff4dd0f054
&a[1] = 0x7fff4dd0f058

p1[0] = 3
p1[1] = 4

p2[0] = 3
p2[1] = 4

      

So, &a[0]

and &a[1]

have the same addresses both in foo(2)

and foo(3)

.

What happens when you enter a function, it usually creates a stack frame (by decreasing the stack pointer by x86). This allocates memory on the stack for automatic storage variables. When you leave the function, the stack frame is destroyed (and the stack pointer returns to its original value). Therefore, if you reintroduce the same function, you usually use the same memory for the stack frame (the stack pointer is decremented to the same value as the last function call).

+7


source


this behavior is undefined, your program may crash as well.

A local variable is stored on the stack, and its lifetime depends only on the scope of the function.



In your case, the program will reuse the same location next time, so your values ​​will be overwritten, but it will not always be the same and will never return the address of a local variable.

+7


source


After each function call memory is allocated on the stack for function variables and the stack pointer is moved forward. Once the stack function is executed, the memory is not erased for efficiency reasons and all data remains there. So if you call the same function a second time and leave some variables uninitialized, you might find some funny values ​​from the last function call. Every array in C is stored as a large chunk of memory where the elements are found when the pointer is moved. As for you, the question is: foo returns a pointer to an integer, which is actually a memory address. After foo (2), p1 will store some address, for example 0x00. Adding curly braces [] with an index to an integer pointer means adding an integer-sized index * to the memory address.We can add any random pointer to the pointer and try to get data from there. If we are lucky and the memory is readable, we will have some garbage data. After the first call to the function

p1 points to a stack array and values are:
p1[0] == 2;
p2[1] == 3;
p1 == 0x00; (for example)

      

The function is executed and returns a pointer to the stack. The next call to foo (3) gets the same chunk of memory on the stack. The second call overwrites the variables with new values. After the second call we get:

p2[0] == 3;
p2[1] == 4;
p2 == 0x00; (same memory address)

      

The problem is that p1 points to the same memory address on the stack. If you call any other function - both p1 and p2 will be changed again because the same stack area will be reused again.

+1


source


In your foo () function, you have a local variable and you are trying to return the address of the local variable. No compiler throws below error:

warning: function returns address of local variable

      

If you need to get the answer you posted then you need to make the array int a[2]

global. Otherwise, we have undefined behavior.

0


source


Removing the stack on return of a function call will free the memory allocated for the array. This memory is no longer available. The behavior is undefined.

0


source







All Articles