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);
At the conclusion of this code snippet, what are the values of each of the following? (answer is given)
在这个代码片段的结尾,以下每一个的值是什么?(回答是)
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 may be reused by something else. In this case, since foo(3) is called immediately after foo(2) at the same call depth (i.e. they use the same stack space), they will both return the same pointer– i.e. p1 is equal to p.
由于a是在堆栈上分配的,所以当调用返回时内存不会继续分配,并且可能被其他东西重用。在这种情况下,由于foo(3)在foo(2)之后以相同的调用深度(也就是说它们使用相同的堆栈空间)调用foo(3),它们都会返回相同的指针——也就是说p1等于p。
I did not understand the above explanation. What does it really mean? Why we have exact same values for p2 and p1? I know that you cannot return a pointer to a local variable in C..but I do not understand why p2 and p1 has same values ....
我不理解上面的解释。它的真正含义是什么?为什么p2和p1的值是相同的?我知道你不能返回一个指向C中的局部变量的指针。但我不明白为什么p2和p1有相同值....
5 个解决方案
#1
7
Using a pointer to automatic storage variables (variables scoped to functions) outside its scope is undefined, which is exactly why you should never do it, and never depend on its behavior.
在其范围之外使用指向自动存储变量(作用域为函数的变量)的指针是没有定义的,这正是为什么您永远不应该这样做,也永远不应该依赖于它的行为。
However, if you want to peel back the cover on the compiler/machine/os, the reason is that the automatic storage happens to be allocated at the same address for the two function calls.
但是,如果您想要将编译器/机器/操作系统的覆盖层剥离,原因是自动存储在两个函数调用的同一个地址中被分配。
An 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 in both foo(2)
and foo(3)
.
[0]和[1]在foo(2)和foo(3)都有相同的地址。
What's happening is that when you enter a function, it generally creates a stack frame (by decrementing the stack pointer on 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 returned to its original value). So if you enter the same function again, you generally use the same memory for the stack frame (stack pointer is decremented to same value as last call to function).
当您输入一个函数时,它通常会创建一个堆栈框架(通过在x86上减少堆栈指针)。这将为自动存储变量分配堆栈上的内存。当您离开函数时,堆栈帧被销毁(堆栈指针返回到原始值)。因此,如果您再次输入相同的函数,您通常会对堆栈帧使用相同的内存(堆栈指针递减到与上次调用函数相同的值)。
#2
7
it is undefined behavior, your program might crash too.
它是未定义的行为,您的程序也可能崩溃。
The local variable is stored on the stack and its life time is only with in the scope of the function.
局部变量存储在堆栈上,其生命周期仅在函数的范围内。
In your case, the program is reusing the same location the next time , so your values are overwritten, but it is not always going to be same and never return address of local variable.
在您的示例中,程序下次将重用相同的位置,因此您的值将被覆盖,但它并不总是相同的,并且永远不会返回本地变量的地址。
#3
1
After each function call memory is allocated on stack for function variables and stack pointer is moved forward. After function execution stack memory is not erased for efficiency reasons and all data stays there. So if you call same function second time and leave some variables uninitialized you can find some funny values from last function call. Every array in C is stored as a big chunk of memory where elements are found by shifting pointer. As for you question: foo returns pointer to integer, which is actually a memory address. After foo(2) p1 will store some address for example 0x00. Adding braces [] with index to a integer pointer means to add an integer size * index to a memory address. We may add any random index to pointer and try to get data from there. If we get lucky and memory is readable - we will have some garbage data. After first function call
在为函数变量分配每个函数调用内存后,栈指针向前移动。在函数执行之后,由于效率原因栈内存不会被删除,所有的数据都留在那里。如果你第二次调用相同的函数并且保留一些未初始化的变量你可以从上次的函数调用中找到一些有趣的值。C中的每个数组都存储为一个大的内存块,通过移动指针查找元素。对于您的问题:foo返回指针到integer,它实际上是一个内存地址。在foo(2) p1之后将存储一些地址,例如0x00。向整数指针添加带索引的大括号[]意味着向内存地址添加一个整数大小*索引。我们可以向指针添加任何随机索引并尝试从那里获取数据。如果运气好的话,内存是可读的,我们就会有一些垃圾数据。第一个函数调用后
p1 points to a stack array and values are:
p1[0] == 2;
p2[1] == 3;
p1 == 0x00; (for example)
Function is executed and it returns stack pointer back. Next function call foo(3) gets same memory chunk on stack. Second call rewrites variables with new values. After second call we get:
函数被执行,它返回堆栈指针。下一个函数调用foo(3)在堆栈上获得相同的内存块。第二个调用使用新值重写变量。第二次通话后,我们得到:
p2[0] == 3;
p2[1] == 4;
p2 == 0x00; (same memory address)
The problem is that p1 points to same memory address on stack. If you call any other function - both p1 and p2 will be changed again, because same region of stack will be reused again.
问题是p1指向堆栈上相同的内存地址。如果您调用任何其他函数——p1和p2都将再次被更改,因为相同的堆栈区域将再次被重用。
#4
0
Stack unwind while returning from the function call will release the memory allocated for the array. That memory is no longer available. The behavior is undefined.
从函数调用返回的堆栈展开将释放为数组分配的内存。内存不再可用。这种行为是未定义的。
#5
0
In your function foo() you have a local variable and your are trying to return the address of the local variable. Don't your compiler throw the below error:
在函数foo()中有一个局部变量,并试图返回局部变量的地址。不要让你的编译器抛出以下错误:
warning: function returns address of local variable
If you have to get the answer you have posted then you need to make the array int a[2]
global. Else we have an undefined behavior here.
如果您必须获得已发布的答案,那么您需要将数组int设置为[2]全局。否则我们就有一个未定义的行为。
#1
7
Using a pointer to automatic storage variables (variables scoped to functions) outside its scope is undefined, which is exactly why you should never do it, and never depend on its behavior.
在其范围之外使用指向自动存储变量(作用域为函数的变量)的指针是没有定义的,这正是为什么您永远不应该这样做,也永远不应该依赖于它的行为。
However, if you want to peel back the cover on the compiler/machine/os, the reason is that the automatic storage happens to be allocated at the same address for the two function calls.
但是,如果您想要将编译器/机器/操作系统的覆盖层剥离,原因是自动存储在两个函数调用的同一个地址中被分配。
An 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 in both foo(2)
and foo(3)
.
[0]和[1]在foo(2)和foo(3)都有相同的地址。
What's happening is that when you enter a function, it generally creates a stack frame (by decrementing the stack pointer on 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 returned to its original value). So if you enter the same function again, you generally use the same memory for the stack frame (stack pointer is decremented to same value as last call to function).
当您输入一个函数时,它通常会创建一个堆栈框架(通过在x86上减少堆栈指针)。这将为自动存储变量分配堆栈上的内存。当您离开函数时,堆栈帧被销毁(堆栈指针返回到原始值)。因此,如果您再次输入相同的函数,您通常会对堆栈帧使用相同的内存(堆栈指针递减到与上次调用函数相同的值)。
#2
7
it is undefined behavior, your program might crash too.
它是未定义的行为,您的程序也可能崩溃。
The local variable is stored on the stack and its life time is only with in the scope of the function.
局部变量存储在堆栈上,其生命周期仅在函数的范围内。
In your case, the program is reusing the same location the next time , so your values are overwritten, but it is not always going to be same and never return address of local variable.
在您的示例中,程序下次将重用相同的位置,因此您的值将被覆盖,但它并不总是相同的,并且永远不会返回本地变量的地址。
#3
1
After each function call memory is allocated on stack for function variables and stack pointer is moved forward. After function execution stack memory is not erased for efficiency reasons and all data stays there. So if you call same function second time and leave some variables uninitialized you can find some funny values from last function call. Every array in C is stored as a big chunk of memory where elements are found by shifting pointer. As for you question: foo returns pointer to integer, which is actually a memory address. After foo(2) p1 will store some address for example 0x00. Adding braces [] with index to a integer pointer means to add an integer size * index to a memory address. We may add any random index to pointer and try to get data from there. If we get lucky and memory is readable - we will have some garbage data. After first function call
在为函数变量分配每个函数调用内存后,栈指针向前移动。在函数执行之后,由于效率原因栈内存不会被删除,所有的数据都留在那里。如果你第二次调用相同的函数并且保留一些未初始化的变量你可以从上次的函数调用中找到一些有趣的值。C中的每个数组都存储为一个大的内存块,通过移动指针查找元素。对于您的问题:foo返回指针到integer,它实际上是一个内存地址。在foo(2) p1之后将存储一些地址,例如0x00。向整数指针添加带索引的大括号[]意味着向内存地址添加一个整数大小*索引。我们可以向指针添加任何随机索引并尝试从那里获取数据。如果运气好的话,内存是可读的,我们就会有一些垃圾数据。第一个函数调用后
p1 points to a stack array and values are:
p1[0] == 2;
p2[1] == 3;
p1 == 0x00; (for example)
Function is executed and it returns stack pointer back. Next function call foo(3) gets same memory chunk on stack. Second call rewrites variables with new values. After second call we get:
函数被执行,它返回堆栈指针。下一个函数调用foo(3)在堆栈上获得相同的内存块。第二个调用使用新值重写变量。第二次通话后,我们得到:
p2[0] == 3;
p2[1] == 4;
p2 == 0x00; (same memory address)
The problem is that p1 points to same memory address on stack. If you call any other function - both p1 and p2 will be changed again, because same region of stack will be reused again.
问题是p1指向堆栈上相同的内存地址。如果您调用任何其他函数——p1和p2都将再次被更改,因为相同的堆栈区域将再次被重用。
#4
0
Stack unwind while returning from the function call will release the memory allocated for the array. That memory is no longer available. The behavior is undefined.
从函数调用返回的堆栈展开将释放为数组分配的内存。内存不再可用。这种行为是未定义的。
#5
0
In your function foo() you have a local variable and your are trying to return the address of the local variable. Don't your compiler throw the below error:
在函数foo()中有一个局部变量,并试图返回局部变量的地址。不要让你的编译器抛出以下错误:
warning: function returns address of local variable
If you have to get the answer you have posted then you need to make the array int a[2]
global. Else we have an undefined behavior here.
如果您必须获得已发布的答案,那么您需要将数组int设置为[2]全局。否则我们就有一个未定义的行为。