You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言栈分配缓冲区函数返回后未释放的原因及行为分析

栈内存释放的疑问与行为分析

问题背景

在以下C程序中,调用函数时会创建一个较大的局部变量buf,函数返回后程序进入无限循环。调用函数时,系统RAM占用量会增加buf大小的空间,符合预期;但函数返回(输出“Done”)后,RAM占用量并未下降,而是保持稳定。

为何该栈分配的缓冲区在函数返回后未立即释放?如何归纳这种通用行为,以及描述其可能立即释放或不释放的场景?

#include <stdlib.h>
#include <stdio.h>

void f()
{
    int buf[1000 * 1000 * 200];
}

int main()
{
    f();
    printf("Done\n");
    for (;;);
    return 0;
}

程序运行时的RAM占用时间线显示:调用函数f时内存占用显著上升,函数返回输出“Done”后,内存占用保持高位不再下降。

补充说明:测试环境为Linux Ubuntu,编译未启用编译器优化;若以“闪烁”方式重复调用f(调用-延迟-返回-延迟),RAM占用时间线类似。


原因分析

栈内存的管理由**进程的栈指针(ESP/RSP寄存器)**控制,而非直接向操作系统申请/释放内存:

  • 调用函数f时,栈指针会向下移动(扩展栈空间)来容纳buf,如果栈扩展超出了当前进程已分配的栈内存区域,操作系统会自动为进程分配更多物理内存映射到栈地址空间。
  • 函数返回时,栈指针只是向上移动回原位置,标记这部分栈空间“可复用”,但不会主动通知操作系统回收物理内存。操作系统无法感知栈内空间是否被使用,只会认为进程的地址空间仍需要这部分内存映射,因此不会释放对应的物理RAM。

通用行为归纳

  • 栈内存的“释放”是进程内部的逻辑标记,仅通过调整栈指针完成,不会触发操作系统层面的物理内存回收。
  • 从系统视角看,进程的内存占用是已申请的物理内存总量,只要进程地址空间还保留对该内存的映射,系统就不会主动回收。
  • 栈空间被标记为可复用后,后续栈操作(如调用其他函数)会直接覆盖这部分空间,不会再次向系统申请新内存。

立即释放/不释放的场景

可能触发系统回收栈内存的场景

  • 进程主动调用brk()/sbrk()或特定系统调用(依赖操作系统实现)收缩栈的地址空间映射,但这不属于标准C行为。
  • 进程退出时,操作系统会回收该进程所有内存资源,包括栈内存。
  • 部分嵌入式系统或特殊内存管理环境中,栈内存可能被实时回收,属于小众场景。

不会立即释放的场景

  • 绝大多数通用操作系统(Linux、Windows、macOS等)的常规用户态进程,函数返回后栈内存仅被标记为可复用,不会触发系统回收。
  • 进程仍在运行且未主动收缩地址空间时,已分配的栈物理内存会被保留,直到进程退出或系统内存紧张(如Linux的OOM机制触发)时才会被回收。

内容的提问来源于stack exchange,提问作者Ramanewbie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 22:35:05