C 返回指向堆栈中存储的变量的指针

C 返回指向堆栈中存储的变量的指针,c,C,我目前正在学习C语言,如果我的问题很愚蠢,请你向我道歉 就我而言,返回指向存储在堆栈中的变量的指针是个坏主意,因为当函数返回时,包含该变量的内存会被清除。因此,我希望在执行以下代码时出现分段错误: int *foo() { int j = 5; int *ptr = &j; return ptr; } int main() { int *p; p = foo(); printf("%d\n", *p); return 0; }

我目前正在学习C语言,如果我的问题很愚蠢,请你向我道歉

就我而言,返回指向存储在堆栈中的变量的指针是个坏主意,因为当函数返回时,包含该变量的内存会被清除。因此,我希望在执行以下代码时出现分段错误:

int *foo()
{
    int j = 5;
    int *ptr = &j;
    return ptr;
}

int main()
{
    int *p;
    p = foo();
    printf("%d\n", *p);

    return 0;
}
然而,当使用gcc版本8.3.0编译时,该程序显然运行良好,没有编译器警告,并且输出5,而不是分段错误。我的问题是,为什么这段代码在本不应该工作的情况下还能工作


提前谢谢你

是的,返回局部变量的地址是个坏主意,因为当函数返回时,局部j不再存在,而指针现在无效

但是,取消引用无效指针并不一定会导致segfault。行为是未定义的,这意味着任何事情都可能发生,包括看起来正常工作

可能发生的情况是,堆栈中包含j的部分尚未被覆盖,因此printf恰好可以工作

…当函数返回时,包含变量的内存将被清除

这是不对的。当函数返回时,其本地对象的存储不再保留用于这些对象

C标准规定,当对象的生命周期开始时,会为其保留存储内存。这意味着C实现提供了一些可用于该对象的内存,而不会用于任何其他目的。当对象的生命周期结束时,C标准表示不再保留存储。该标准没有说明内存已清除或未映射。它也没有说它未被清除或未被映射


C实现可以清除内存,但普通C实现不能,因为这通常是一种资源浪费。最常见的情况是,内存在用于其他用途之前保持不变。但也可能有其他影响,例如从进程的虚拟地址空间中删除内存。因此,在函数返回之后和调用任何其他改变内存的函数之前,可以使用内存是正常的,但是如果使用内存,程序中也会出现错误也是正常的。无论哪种方式都不能保证该行为。

您启用了哪些其他标志-你的程序有未定义的行为,其中包括工作正常。输出的5只是内存中的剩余部分,可以随时被覆盖。复制打印文件%d\n,p;并查看第二个printfi上的输出。它可能不是5。我使用-Wall标志编译,gcc没有给出任何警告消息。;当我复制printf%d\n时,*p;我得到5张打印的2张times@L.Borislavov在我的电脑上,我第二次得到另一个号码。正如我之前写的,这是一个未定义的行为,非常感谢!现在我明白了。