2

可能重复:
可以在其范围之外访问局部变量的内存吗?
局部变量的返回地址

我有一个问题,首先看代码

    #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 并且当函数返回或完成执行时,它的值将从内存位置中删除。我尝试了这段代码,答案当然是 10 和地址,我使用 GNU/GCC 编译器。谁能说出什么是对什么是错。提前致谢。

4

5 回答 5

3

您的老师是绝对正确的:即使您将程序修复为 returnint*代替int,您的程序仍然包含未定义的行为。问题是a曾经放置的内存已经成熟,可以在sum返回后重用。内存可能保持不变供您访问,因此您甚至可以打印十个,但这种行为仍然未定义:它可能在一个平台上运行并在其他十个平台上崩溃。

于 2012-08-18T01:18:43.947 回答
2

你可能会得到正确的结果,但这只是因为你很幸运,当 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 时,会发生奇怪的事情,因为它指向的内存可能完全被搞砸了。

于 2012-08-18T01:22:25.780 回答
0

您的指针仍然指向您的 10 所在的内存位置。但是,从 Cs 的角度来看,内存是未分配的,可以重用。在堆栈上放置更多项目或分配内存可能会导致该部分内存被重用。

于 2012-08-18T01:18:50.543 回答
0

函数 sum 中的对象aautomatic lifetimereturn一旦程序流(函数末尾的语句)离开它在(函数体)中声明的范围,它的生命周期就会结束。

之后,访问所a居住的内存将按照您的预期进行,召唤龙或让您的计算机着火。这在 C 中称为未定义行为。然而,C 标准本身没有说明,deleting something from memory因为它没有内存的概念。

于 2012-08-18T01:33:08.540 回答
0

从逻辑上讲,一旦退出a就不再存在;sum它的生命周期仅限于函数的范围。 从物理上讲,a占用的内存仍然存在,并且仍然包含值 10 的位模式,但是该内存现在可供其他东西使用,并且可能在您使用之前被覆盖main。您的输出可能是 10,也可能是垃圾。

试图在该变量的生命周期之外访问该变量的值会导致未定义的行为,这意味着编译器可以自由地以任何它想要的方式处理这种情况。它不必警告你你正在做任何奇怪的事情,它不必按照你期望的方式工作,它根本不需要工作。

于 2012-08-18T12:50:45.990 回答