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

标签 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;
}

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

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

  2. 如果我删除“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/

相关文章:

c++ - Visual Studio 2010 C++ : Get size of memory block allocated by malloc

c - 像正常对象的指针那样传递函数指针并对其进行比较是否安全?

c - 在 C 中分配大内存(Project Euler Prob)

c - 当函数返回时,临时存储在 C 中如何工作?

php - Yii NestedSetBehavior 内存使用情况

Scala 生成列表的排列耗尽内存

c - 如何按字母顺序对结构进行冒泡排序

c - 结构数组操作

c++ - 关于学习 Xlib ("the Linux Petzold"的书籍/资源?)

c - 什么时候将内存分配给C中的局部变量