当本地函数的内存在堆栈上被清除时?

when the memory is cleared on stack for a local function?

我想知道分配给本地函数调用的堆栈中的内存究竟何时被清除。我在一些视频教程中看到,当函数调用返回到 main 时,分配给本地函数的内存被清除。我对下面的程序有几个问题,请解释。

#include<stdio.h>

void print(){
printf("testing \n");
}

int* sum(int* a, int* b){
int c = *a + *b;
return &c;
}

int main(){
int a=3,b=2;
int *ptr = sum(&a,&b);
print();          
printf("sum is: %d",*ptr);
return 0;
}

当我运行上面的程序时,它正在打印预期的垃圾值。但是,如果我在 main 中注释 "print()" 函数,然后在程序中注释 运行 它正在打印正确的总和值。

  1. 这是否意味着即使本地函数在栈中执行完成,直到有另一个函数调用栈,之前分配的内存不会被清除?

  2. 如果我删除 "print()" 中的 "printf" 语句并保留 main 中的 "print()" 调用,那么我可以正常看到求和结果。为什么它没有覆盖堆栈中的内存?

Chas没有堆栈,标准中甚至没有提到堆栈这个词(C89,C99orC11)。 实现 可以使用堆栈来提供 C 抽象机的行为方面,但标准指定的是抽象机本身。

因此,至于何时清除堆栈(假设它甚至存在),这完全取决于实现。您所做的基本上是未定义的行为,在对象的生命周期结束后访问对象,因此结果可以是实现选择的任何内容。

至于为什么您可以在 特定 实现的生命周期结束后访问这些项目,很可能是因为进入和退出函数 不会 清除堆栈,它只是调整堆栈指针(比必须清除内存更有效)。

因此,除非有什么东西覆盖了该内存位置的内容(例如对 printf 的后续调用),否则它可能会保留在上次设置的位置。

例如,这里有一个函数的示例序言代码:

push  ebp       ; Save the frame pointer.
mov   ebp, esp  ; Set frame pointer to current stack pointer.
sub   esp, XX   ; Allocate XX space for this frame.

及其等效的结尾:

mov   esp, ebp  ; Restore stack pointer.
pop   ebp       ; Get previous frame pointer.
ret             ; Return.

请注意,space 的分配(序言中的 sub)和它的释放(结语中的mov)实际上都清除 它正在使用的内存。

但是,如前所述,这不是您应该依赖的东西。

您问题的答案是特定于操作系统的。在从头开始创建进程的系统中 (VMS/NT),只有在创建进程时才会清除堆栈。堆栈是从需求零页面创建的。当第一次访问堆栈页时,操作系统会创建一个新的零页。

在分叉系统中,每当加载新的可执行文件时,堆栈就会被清除。通常过程同上。

创建堆栈后,放在那里的任何内容都会保留在那里,直到被覆盖。

堆栈由操作系统管理;不是编程语言。