为什么局部变量的值有时在函数结束后仍然存在?

Why does the value of a local variable sometimes persist after the function ends?

我一直在努力了解一旦函数执行完成后函数内部的局部变量是如何被释放的,因为该函数调用的堆栈帧被“弹出”堆栈。

我写了一些代码来测试这个:

int* func1(void){
    int a = 10; 
    return &a; 
}
int main(void){
    int* h = func1(); 
    printf("%d \n", *h); 

    return 0; 
}

这导致了“分段错误..”,这是我所期望的,因为 &a 处的内存现在是空闲的。

然而,令我感到困惑的是,当我在 func1 中创建一个指向“a”的指针并且 returns 该指针时,“a”的值似乎在之后仍然存在。

这里是代码:

int* func1(void){
    int a = 10; 
    int* b = &a;
    return b; 
}


int main(void){
    int* h = func1(); 
    printf("%d \n", *h); 

    return 0; 
}

我得到的这段代码的输出是“10”。 为什么这段代码让“a”的值持续存在??

返回局部变量的地址是非法的。一些编译器检测到这一点,而不是 returning 局部变量的实际地址,编译器使函数 return 成为 NULL 指针。

这很可能是您第一个示例中发生的情况。因此,当您取消引用指针(又名 return 值)时,程序会崩溃。

在第二个示例中,您的编译器未检测到 return 值是局部变量的地址,因此该地址实际上是 returned。当您取消引用指针(又名 return 值)时,恰好函数的“旧”值仍然存在于该地址。

在这两种情况下,您的代码都有未定义的行为。实际发生的情况取决于您的特定系统。

尝试打印 return 值,例如:

int* func1(void){
    int a = 10; 
    printf("In func1: Address of a is %p\n", &a);
    return &a; 
}

int* func2(void){
    int a = 10; 
    printf("In func2: Address of a is %p\n", &a);
    int* b = &a;
    return b; 
}

int main(void){
    int* h = func1(); 
    printf("Value returned by func1:  %p \n", (void*)h); 
    int* hh = func2(); 
    printf("Value returned by func2:  %p \n", (void*)hh); 

    return 0; 
}

我的输出:

In func1: Address of a is 0x7ffdc3bc0a6c
Value returned by func1:  (nil) 
In func2: Address of a is 0x7ffdc3bc0a6c
Value returned by func2:  0x7ffdc3bc0a6c 

Why does the value of a local variable sometimes persist after the function ends?

大多数系统(如果不是全部)在函数调用期间使用预分配的内存块 - 称为堆栈。堆栈指针告诉当前正在使用的内存块有多少。当一个函数被调用时,堆栈指针被更改为使用更多的内存块(即存储函数局部变量和可能的其他东西)。当函数 returns 时,堆栈指针再次变回旧值。但是不需要以任何方式更改函数使用的内存。因此,如果您在函数 return 之后(非法)访问该函数正在使用的堆栈内存,您可能会看到旧值仍然存在。