当堆栈清除内存以获取本地功能时?

vid*_*dya 1 c memory-management

我想知道何时在堆栈中清除了内存,这是为本地函数调用分配的.我在一些视频教程中看到,当函数调用返回到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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

pax*_*blo 6

Ç 具有无堆叠,所述字堆栈未在标准(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.
Run Code Online (Sandbox Code Playgroud)

及其等效的结语:

mov   esp, ebp  ; Restore stack pointer.
pop   ebp       ; Get previous frame pointer.
ret             ; Return.
Run Code Online (Sandbox Code Playgroud)

请注意,空间的分配(sub在prolog中)和它的释放(mov在epilog中)实际上都不会清除它正在使用的内存.

但是,如上所述,这不是你应该依赖的东西.