C语言 在 main 中调用此函数时,是否从内存中删除局部变量



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

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

    #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,也可能是垃圾。

尝试在变量

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

最新更新