单片机内存分配管理笔记

本示例使用vscode中cubemx插件,芯片STM32G411CUE6,Flash、RAM分配示意图如下:

一、编译链接阶段静态划分

1. text 段(代码段 / 文本段)

存储内容:程序的机器码(函数体、指令)、const修饰的只读常量(如const int g_val = 10;);

物理映射:唯一映射到Flash(非易失、只读,防止程序代码被意外修改);

核心特性:编译链接后固化,运行时不可修改,占用 Flash 空间,不占用 RAM 空间;

2. rodata 段(只读数据段)

存储内容:字符串常量(如"hello world")、未用const修饰但实际只读的常量;

物理映射:映射到Flash(只读,非易失);

与 text 段的关系:text 段偏 "执行指令",rodata 段偏 "只读数据",本质都是 Flash 中的只读内容。

3. data 段(已初始化数据段)

存储内容:显式赋初始值的全局变量、显式赋初始值的静态变量(static修饰),如int g_init = 10;static char s_buf = 'a';

物理映射:双占用特性------ 初始值存 Flash(烧录时固化),运行时变量本体存 RAM(可读写);

核心特性:程序上电启动后,启动文件会自动将 Flash 中的初始值拷贝到 RAM的 data 段区域,完成变量初始化;

与 BSS 段的核心区别:都是存全局 / 静态数据、都占 RAM,但 data 段需要 Flash 存初始值,BSS 段不需要。

4. bss 段(未初始化数据段)

存储内容:未显式赋初始值的全局变量、未显式赋初始值的静态变量,如int g_uninit;static long s_uninit;

物理映射:仅占用 RAM,不占用任何 Flash 空间(核心特性,无初始值可存储,无需烧录);

核心特性:程序上电启动后,启动文件会自动将 bss 段对应的 RAM 区域全部清零(赋 0),因此未初始化的全局 / 静态变量默认值一定是 0;

二、程序运行时的RAM 动态内存区域

1. 栈区(Stack)------ 自动管理

存储内容:局部变量(函数内定义的非 static 变量,如void func(){ int a; })、函数调用的返回地址、函数参数、寄存器临时值;

管理方式:编译器自动分配和释放,函数调用时,局部变量入栈;函数执行结束,局部变量出栈,内存自动回收;

核心特性:① 地址向下生长(从高地址向低地址分配内存);② 有固定大小限制(小心溢出);③ 局部变量默认值随机(不会被清零,与 BSS 段的 "自动清零" 形成鲜明对比);

与 BSS 段的核心区别:

对比维度 栈区 BSS 段
存储数据 局部变量、函数参数 未初始化全局 / 静态变量
管理方式 编译器自动管理 链接器静态分配
生命周期 随函数调用结束消失 整个程序运行周期
初始化方式 无,默认随机值 启动文件自动清零

2. 堆区(Heap)------ 手动管理

存储内容:程序员通过动态内存函数申请的内存,如 C 标准库的malloc()calloc()realloc(),单片机裸机开发中也可自定义堆区申请函数;

管理方式:程序员手动分配和释放------ 申请后必须用free()释放,否则会造成内存泄漏;

核心特性:① 地址向上生长(从低地址向高地址分配内存);② 无固定大小限制(最大为 RAM 中未被其他区域占用的剩余空间);③ 是单片机动态内存分配的唯一方式(如运行时根据需求创建数组、缓冲区);

与 BSS 段的核心区别:BSS 段是静态分配(编译链接时确定大小),堆区是动态分配(运行时确定大小);BSS 段由系统管理,堆区由程序员手动管理。

三、对比表

内存层级 区域名称 存储核心内容 映射 分配阶段 管理方式 初始化方式 生命周期
逻辑段(静态) text 机器码、const 只读常量 Flash 编译链接 链接器 编译固化,不可修改 整个程序运行期
逻辑段(静态) rodata 字符串常量、只读数据 Flash 编译链接 链接器 编译固化,不可修改 整个程序运行期
逻辑段(静态) data 已初始化全局 / 静态变量 RAM 编译链接 链接器 启动时从 Flash 拷贝到 RAM 整个程序运行期
逻辑段(静态) bss 未初始化全局 / 静态变量 RAM 编译链接 链接器 启动文件自动清零(赋 0) 整个程序运行期
运行时区域(动态) 栈区 局部变量、函数参数、返回地址 RAM 程序运行 编译器自动 无,默认随机值 随函数调用结束
运行时区域(动态) 堆区 动态申请的内存(malloc 等) RAM 程序运行 程序员手动 无,默认随机值(calloc 除外) 手动释放前

四、实践

使用CMake中的辅助工具,可以清晰看到代码编译后的内存分配

data段数据示例(static uint8_t 编译后被归类到RAM data段)

bss数据段示例(未进行初始化或初始化为0的数据被编译归类为RAM bss段,注:STATE_WAIT_START = 0)

text数据段示例(函数SQUARE_Init被编译后归类到Flash text)

rodata数据段示例(const字体数组被编译归类到Flash rodata段)

相关推荐
阿里嘎多学长3 小时前
2026-02-16 GitHub 热点项目精选
开发语言·程序员·github·代码托管
啊吧怪不啊吧4 小时前
C++之基于正倒排索引的Boost搜索引擎项目usuallytool部分代码及详解
开发语言·c++·搜索引擎·项目
FakeOccupational5 小时前
【电路笔记 通信】数字混频(采样做频谱搬移)+频率混叠(aliasing)公式证明+带通采样示例
笔记
CeshirenTester5 小时前
9B 上端侧:多模态实时对话,难点其实在“流”
开发语言·人工智能·python·prompt·测试用例
发现你走远了5 小时前
Windows 下手动安装java JDK 21 并配置环境变量(详细记录)
java·开发语言·windows
游乐码5 小时前
c#类和对象
开发语言·c#
黎雁·泠崖6 小时前
Java常用类核心详解(一):Math 类超细讲解
java·开发语言
懒惰成性的6 小时前
12.Java的异常
java·开发语言
-To be number.wan6 小时前
Python数据分析:时间序列数据分析
开发语言·python·数据分析
前路不黑暗@7 小时前
Java项目:Java脚手架项目的通用组件的封装(六)
java·开发语言·spring