可能的重复项:
是否可以在其范围之外访问局部变量的内存?
返回局部变量的地址
我有一个问题,首先看一下代码
#include <stdio.h>
int sum(); /* function declaration */
int main()
{
int *p2;
p2 = sum(); /* Calling function sum and coping its return type to pointer variable p2 */
printf("%d",*p2);
} /* END of main */ `
int sum()
{
int a = 10;
int *p = &a;
return p;
} /* END of sum */
我认为答案是 10 和变量 a 的地址,但我的 tesacher 说 a 是函数的本地函数,所以 a 和它的当函数返回或完成执行时,值将从内存位置删除。我尝试了这段代码,答案当然是 weel 10 和地址,我使用 GNU/GCC 编译器。谁能说什么是对的,什么是错的。提前谢谢。
你的老师是绝对正确的:即使你修复了你的程序以返回int*
代替int
,你的程序仍然包含未定义的行为。问题在于,一旦sum
返回,过去放置a
的内存已经成熟,可以重用。内存可能会保持不变供您访问,因此您甚至可以打印十个,但此行为仍未定义:它可能在一个平台上运行并在其他十个平台上崩溃。
你可能会得到正确的结果,但这只是因为你很幸运,当 sum() 返回时,a 的内存被返回到系统,它可以被任何其他变量使用,所以值可能会被更改。
例如:
#include <stdio.h>
int* sum(); /* function declaration */
int* sum2(); /* function declaration */
int main()
{
int *p2;
p2 = sum(); /* Calling function sum and coping its return type to pointer variable p2 */
sum2();
printf("%d",*p2);
}
int* sum()
{
int a = 10;
int *p = &a;
return p;
} /* END of sum */
int* sum2()
{
int a = 100;
int *p = &a;
return p;
} /* END of sum */
使用此代码,a 将被 sum2() 重用,从而用 100 覆盖内存值。
在这里,你只返回一个指向 int 的指针,假设你返回一个对象:
TestClass* sum()
{
TestClass tc;
TestClass *p = &tc;
return p;
}
然后,当您取消引用tc时,会发生奇怪的事情,因为它指向的内存可能完全搞砸了。
指针仍然指向内存中 10 所在的位置。 但是,从 C 的角度来看,内存是未分配的,可以重用。 在堆栈上放置更多项目或分配内存可能会导致该部分内存被重用。
函数 sum 中a
的对象具有 automatic lifetime
。一旦程序流(函数末尾的 return
语句)留下了声明它的范围(函数体),它的生命周期就会结束。
之后,访问a
生活的内存将执行您的期望,召唤龙或点燃您的计算机。这在 C 语言中称为未定义行为。然而,C标准本身并没有提到deleting something from memory
,因为它没有内存的概念。
从逻辑上讲,一旦sum
退出,a
就不再存在;它的生存期仅限于函数的范围。 从物理上讲,a
占用的内存仍然存在,并且仍然包含值 10 的位模式,但该内存现在可供其他东西使用,并且可能会在您可以使用它之前被覆盖 main
. 您的输出可能是 10,也可能是垃圾。
的生存期之外访问变量的值会导致未定义的行为,这意味着编译器可以自由地以任何它想要的方式处理这种情况。 它不必警告你你正在做任何令人讨厌的事情,它不必按照你期望的方式工作,它根本不需要工作。