我想知道分配给本地函数调用的堆栈中的内存究竟何时被清除。我在一些视频教程中看到,当函数调用返回到 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()”函数,然后运行该程序,它会打印出正确的总和值。
这是否意味着即使本地函数的执行在栈中完成,直到有另一个函数调用栈,之前分配的内存不会被清除?
如果我删除“print()”中的“printf”语句并保留 main 中的“print()”调用,那么我可以正常看到求和结果。为什么它没有覆盖堆栈中的内存?
最佳答案
C 没有 堆栈,标准(C89、C99 或 C11)中甚至没有提到堆栈这个词。 实现可以使用堆栈来提供 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.
请注意,空间分配(序言中的 sub
)和空间的释放(epilog 中的 mov
)实际上清除它正在使用的内存。
但是,如前所述,您不应该依赖它。
关于c - 当本地函数的内存在堆栈上被清除时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29875558/