13.程序分段.md 3.9 KB

程序分段

判别规则(核心,唯一要记的)

  • 判据一句话:指令 → .text;const → .rodata;有非零初值的全局/static → .data;无初值或初值为 0 的全局/static → .bss;局部变量 → 栈;malloc → 堆
  • 嵌入式核心:RAM 要装 data 副本 + BSS + 堆 + 栈;Flash 只装 text + rodata + data 初值。BSS 不占 Flash = 省空间

一句话:"有字进 data,全零进 bss;Flash 装代码和初值,RAM 装可变和动态。"

抽象描述(一句话本质)

程序编译链接后的内存布局分六块:.text(指令)、.rodata(const)、.data(有初值变量)、.bss(零初值变量)、堆、栈。判据核心 = "这段数据会不会变"——不变的进 Flash,会变的进 RAM。

正反例(建立直觉)

  • 正例1(.text):机器指令,只读,Flash/ROM
  • 正例2(.data)int g = 5; static int s = 10; 有非零初值 → 初值存 Flash,启动时拷到 RAM 的 .data 副本(RAM 才能改)
  • 正例3(.bss)int g; static int s = 0; → 启动清零,不占 Flash(初值全 0 不用存)→ 省 Flash
  • 正例4(堆+栈):堆 = malloc 动态分配向上增长;栈 = 局部变量向下增长,函数调用期
  • 反例1int g = 0; → BSS!"初始化为 0"和"未初始化"在段里是一家
  • 反例2:const 全局变量 → .rodata 不是 .data——不改就直接放 Flash,不用拷 RAM(省 RAM)

易混对比(六段)

存什么 初始化 嵌入式位置
.text 代码段 机器指令 Flash,只读
.rodata 只读数据 const 常量 Flash,只读
.data 数据段 已初始化非零的全局/static 有初值,启动拷贝 初值 Flash,运行 RAM
.bss 未初始化/初始化为 0 的全局/static 启动清零 RAM(不占 Flash
malloc RAM,动态
局部变量 RAM,动态

变体验证(3 题,全过=学会)

  1. static int counter = 0;(函数内)→ BSS(初值 0,"初始化为 0"和"未初始化"是一家)
  2. 陷阱题:全局未初始化 int arr[1000];不占 Flash(BSS 在 RAM 清零)
  3. 陷阱题:启动代码对 .data 和 .bss 各做什么 → .data 初值从 Flash 拷到 RAM;.bss 清零

口述要点(面试怎么讲)

  • 结论先行:六段(text/rodata/data/bss/堆/栈),判据 = "这段数据会不会变"
  • 为什么区分 .data 和 .bss:BSS 初值全 0 不用存 Flash → 省 Flash 资源。Flash 也是稀缺资源,少存一份 0 的初值就多一片空间
  • .rodata vs .data:rodata 不改 → 直接 Flash 引用,省 RAM(不用拷贝副本);data 要改 → 必须拷贝到 RAM 才能改。const 进 rodata 不进 data 就是这个道理
  • 启动流程(Q3 完整版,面试必背)

    上电 → 复位向量 → 设置栈指针 SP → 拷贝 .data 初值(Flash→RAM) → 清零 .bss → 跳转 main()
    

    注意:MCU 上代码直接从 Flash 执行(XIP),没有 PC 那种"加载到内存"的步骤

  • 易错点int g = 0; 进 bss 不是 data;const 进 rodata 不是 data;忘了启动流程里的 SP 初始化

关系网络

相邻概念 和本主题的关系 孤立理解会犯的错
内存分配方式 三区 → 六段完整版:分段图就是"静态区"的细分 以为静态区只有一块,分不清 data/bss/rodata
启动流程 上电 → 拷 data → 清 bss → main,就是分段图的"用法" 忘了 SP 初始化这一步
const const 进 rodata,不改 → 直接 Flash,省 RAM 以为 const 进 .data
结构体对齐 段内数据怎么摆放 以为分段和段内布局无关

学习日期

2026-08-03


每主题一页,复习时只翻本目录。