C语言程序有哪些分段?
那么好,看一段stm32f1的启动代码,可以看到复位中断后进入的是__main这个就是编译器帮我们自动生成的一个函数,里面会自动进行copy data段以及bss段清零的操作,之后再跳转到自己编写main函数中。一般链接到 Flash,CPU 直接从 Flash 取指执行(XIP),不需要搬到 RAM(除非你为了速度做“代码搬运到 RAM 执行”):CPU 实际“访问/执行”时使用的地址,也就是链
程序为什么要分段?.text / .data / .bss 到底有什么区别?
面试经常会问:c语言程序有哪些分段?.text、.data、.bss 到底有什么区别?很多人能背出定义,但不一定理解“为什么必须这样设计”。
要把这个问题讲透,先引入两个非常关键的概念:加载地址(LMA)*和*运行地址(VMA)。
加载地址(Load / LMA):固件镜像“存放”的位置。对 MCU 来说,通常就是 Flash 里的地址(例如 STM32 的 0x0800_0000 开始)。 程序分段
运行地址(Run / VMA):CPU 实际“访问/执行”时使用的地址,也就是链接时为各段安排的运行位置(比如 .data/.bss 常在 RAM)。
以 STM32F 系列为例:程序下载时烧到 Flash;运行时代码通常仍然在 Flash 中 XIP(就地执行),而可读写数据会被放到 RAM。于是 .data 很典型:LMA 在 Flash,VMA 在 RAM
下面用 6 个最经典的区域把它讲清楚:.text、.rodata、.data、.bss、堆、栈。 程序分段
1).text 段:代码放哪里、为什么通常能在 Flash 直接跑?
.text 段存放指令代码,通常是只读的。对 MCU 来说,.text 一般链接到 Flash,CPU 直接从 Flash 取指执行(XIP),不需要搬到 RAM(除非你为了速度做“代码搬运到 RAM 执行”)
2).rodata / .data / .bss:同样是数据,为什么要分三类?
.rodata、.data、.bss 都与“数据”有关,但它们的初始值和是否需要占用镜像空间不同。 程序分段
int value; // 未初始化(默认 0) int value0 = 0; // 初始化为 0 int value1 = 666; // 初始化为非 0
2.1 .data:有“非 0 初值”的全局/静态变量
-
.data段存放:初始化为非 0 的全局变量/静态变量。 程序分段 -
为什么要有
.data:因为这些变量的初值(比如 666)必须被保存下来,否则上电后 RAM 里是随机值。 -
所以
.data的典型形态是:-
LMA 在 Flash:Flash 里存一份“初值镜像”
-
VMA 在 RAM:程序运行时读写的是 RAM 那份
-
启动时会发生:把 Flash 中的 .data 初值拷贝到 RAM 的 .data 运行地址。
2.2 .bss:未初始化/初始化为 0 的全局/静态变量(不占镜像空间)
-
.bss段存放:未初始化或者初始化为 0的全局变量/静态变量。 程序分段 -
.bss的关键特点:不占用实际固件镜像空间(ELF 里通常是 NOBITS),镜像里只需要记录“范围/大小”。 -
启动时会发生:把 RAM 中
.bss对应范围清零。
这时候就有人会问了,主包主包,flash里的数据是怎么移到ram中的呢?
那么好,看一段stm32f1的启动代码,可以看到复位中断后进入的是__main这个就是编译器帮我们自动生成的一个函数,里面会自动进行copy data段以及bss段清零的操作,之后再跳转到自己编写main函数中。

2.3 .rodata:只读常量(const / 字符串常量等)
.rodata 通常存放只读常量(例如 const 全局常量、字符串常量等)。它的加载地址和运行地址通常都在 Flash,从物理上保证“只读”。
3)栈(Stack):自动、快,但溢出很致命
栈是自动管理的、向下增长的临时空间,主要用于:局部变量、函数调用现场保存、中断入栈等。进入/退出函数会自动分配/回收,不需要手动管理。static 修饰的局部变量不在栈上,而在 .data/.bss 这类静态存储区。 程序分段
栈溢出常见原因:递归过深、局部变量过大、(RTOS 下)任务栈配得太小。溢出后常表现为 HardFault/跑飞
5)堆(Heap):灵活,但 MCU 上要谨慎
堆是动态分配的内存(malloc/free),一般向上增长。它更灵活,但在 MCU 上常见问题是:碎片化、实时性差、泄漏难排查。 程序分段
-
内存溢出:一次
malloc过大或长期分配导致超过可用堆空间。 程序分段 -
内存泄漏:分配后没有及时
free,可用堆逐渐被吃光。
在小ram的MCU中尽量使用全局变量,避免用堆可能导致的内存问题。
更多推荐


所有评论(0)