C 语言-内存管理

C 语言-内存管理 文章目录一、C 程序内存两大分配体系划分二、程序整体内存四大分区程序加载进内存后固定布局三、栈内存运行核心规则四、堆内存动态内存接口与底层逻辑五、高频内存错误产生逻辑由内存分区特性直接决定六、各区域生命周期汇总七、文章补充说明本文结合 C 语言标准规范针对单片机、Linux 应用层 C 开发人员拆解程序运行时五大内存分区基础逻辑梳理堆、栈、全局区的分配释放规则、函数调用栈运作机制、malloc/free 底层行为以及内存错误高发场景成因。一、C 程序内存两大分配体系划分编译期静态内存分配编译器在链接阶段就划定内存空间大小程序运行期间地址、容量固定无需手动释放。包含只读常量区、全局数据区、静态变量区。运行期动态内存分配程序执行过程中主动向操作系统申请内存由开发者手动管控生命周期也就是堆内存。搭配函数自动使用的栈内存构成程序动态运行的内存载体。二、程序整体内存四大分区程序加载进内存后固定布局程序被操作系统载入内存后整体分为 4 个区域从上至下地址分布依次为代码段存放编译后的二进制机器指令、函数实体代码。权限只读运行中不可修改字符串常量也寄存于此程序全程不会被释放。全局区放全局变量静态变量data 段初始化的全局变量、初始化 static 静态变量程序启动时分配进程销毁才回收bss 段未初始化全局变量、未初始化 static 变量系统默认填充 0只占用编译符号表空间运行时一次性清零分配。栈区 系统自动管理内存函数调用专属内存空间由 CPU 栈指针寄存器自动分配、函数执行结束自动回收。存放局部普通变量、函数形参、函数返回地址、临时寄存器数据、函数调用现场。栈大小由系统预先设置容量固定。堆区开发者手动管理内存位于 bss 段与栈中间地址向上增长。依靠 malloc、calloc、realloc 申请内存free 主动释放。堆没有固定大小受系统可用物理内存限制生命周期完全由代码控制。三、栈内存运行核心规则1、栈帧运作机制每一次函数调用都会生成独立栈帧函数入栈开辟空间函数执行完毕栈帧自动出栈销毁局部变量随之失效。2、栈核心特性分配释放自动完成无需人为操作执行效率极高空间容量受限递归深度过大、局部数组过长极易造成栈溢出栈内存数据随机脏值局部变量不初始化会携带随机数据。3、典型使用场景函数内部临时变量、数组、结构体临时数据、函数参数传递、函数跳转现场保存。四、堆内存动态内存接口与底层逻辑1、四个核心 API 功能malloc (n)申请 n 字节原始内存内存保留原有脏数据不会清零calloc (num, size)分配 num 个 size 大小内存块分配完成自动清零整块内存realloc (ptr, new_size)扩容 / 缩容已有堆内存大概率会更换内存物理地址free (ptr)释放已申请的堆内存释放后指针变为野指针。使用时需包含 mclloc.h / stdlib.h 头文件2、堆内存分配与释放约束申请和释放必须一一对应单次 malloc 仅允许执行一次 free重复 free 直接引发程序崩溃为了解决这个问题通常会将NULL赋值到已释放内存的指针来防止程序崩溃free 只回收内存使用权交还给操作系统不会清空原有内存数据堆内存地址由操作系统分配地址不连续存在内存碎片问题。五、高频内存错误产生逻辑由内存分区特性直接决定栈溢出局部超大数组、无限递归超出系统栈预设容量程序异常崩溃野指针 / 悬空指针栈局部变量地址返回上层函数、堆内存 free 之后继续使用原指针内存泄漏malloc 申请堆内存程序退出前没有执行 free长时间运行导致内存占用持续走高数组越界访问读写超出数组开辟的内存范围篡改相邻内存数据出现随机性 bug修改只读区数据修改字符串字面量、const 全局常量触发操作系统内存保护报错。六、各区域生命周期汇总代码段、只读段、全局静态区进程运行全程有效进程结束由系统统一回收栈内存随函数调用创建函数返回立刻自动销毁堆内存从 malloc 申请开始生效调用 free 主动释放进程退出系统强制回收所有堆内存。七、文章补充说明本篇为 C 语言内存管理基础篇章只讲解分区划分、基础特性、接口规则。