首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >当内存在堆栈上为本地函数清除时?

当内存在堆栈上为本地函数清除时?
EN

Stack Overflow用户
提问于 2015-04-26 08:47:11
回答 2查看 1.1K关注 0票数 2

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

代码语言:javascript
代码运行次数:0
运行
复制
#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()“函数,然后运行程序,那么它就是打印了正确的sum值。

  1. 这是否意味着即使在堆栈中完成了本地函数的执行,直到对堆栈进行了另一个函数调用,之前分配的内存仍未清除?
  2. 如果删除"print()“中的"printf”语句,并将"print()“调用保留在main中,则可以看到sum的结果是正常的。为什么它没有覆盖堆栈中的内存?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-04-26 08:57:48

C没有堆栈,甚至在标准(C89、C99或C11)中都没有提到堆栈。实现可以使用堆栈来提供C抽象机器的行为方面,但它是标准指定的抽象机器本身。

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

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

因此,除非某个东西覆盖了该内存位置的内容(例如对printf的后续调用),否则它很可能将保持在上次设置的任何位置。

作为示例,下面是一个函数的prolog代码示例:

代码语言:javascript
代码运行次数:0
运行
复制
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.

及其相应的epilog:

代码语言:javascript
代码运行次数:0
运行
复制
mov   esp, ebp  ; Restore stack pointer.
pop   ebp       ; Get previous frame pointer.
ret             ; Return.

请注意,空间的分配(prolog中的sub)和空间的取消分配(epilog中的mov)实际上都没有清除它正在使用的内存。

然而,正如所述,是不应该依赖的.

票数 7
EN

Stack Overflow用户

发布于 2015-04-26 19:36:30

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

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

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

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29875558

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档