【ARM 嵌入式 编译系列 10.4.2 -- 查看 bss 段中有哪些内容】
文章目录
- Overview
- 一、什么是 .bss段?
- 二、查看 .bss 段大小
- 方法 1:使用 size 命令
- 三、查看 .bss 段里都有哪些符号(变量)
- 方法 2:用 `nm` 和 `grep` 查看 `.bss` 中的符号
- 方法 3:用 `objdump` 查看段内容(结构)
- 为什么 .bss 很大?
- 常见原因
- 解决建议
Overview
在代码编译的时候,我们可能会发现 BSS 占用的空间比较大,那么如何使用GCC 相关的工具来
查看bss 端有哪些内容以及为什么这么大呢?
要查看 GCC 构建出来的程序中 .bss
段的内容和大小,需要理解两部分:
-
.bss
是什么,它里面为什么“看起来很大” -
怎么实际查看
.bss
里有哪些符号(变量)以及它们占用的空间
一、什么是 .bss段?
-
.bss
(Block Started by Symbol)段用于存放 未初始化的全局变量和静态变量。 -
它在编译时 不占用实际空间,但在运行时由加载器或运行时初始化为全 0。
-
编译器只是告诉链接器:“这段内存我以后要用,占 X 字节,但你不用给我写入文件。”
举例:
int a; // 位于 .bss 段
static int b; // 位于 .bss 段
char buf[4096]; // 如果是全局/静态,位于 .bss 段
二、查看 .bss 段大小
方法 1:使用 size 命令
size your_program.elf
输出示例:
text data bss dec hex filename1024 512 65536 67072 10500 your_program.elf
-
.text
:代码段大小 -
.data
:已初始化的全局变量 -
.bss
:未初始化的变量大小 -
dec
/hex
:总大小(十进制/十六进制)
上面显示
.bss
有 64KB,很可能是因为你有一个大数组,或某个库全局变量预留了大内存空间。
三、查看 .bss 段里都有哪些符号(变量)
方法 2:用 nm
和 grep
查看 .bss
中的符号
nm -S --size-sort your_program.elf | grep ' [Bb] '
-
-S
:显示每个符号的大小 -
--size-sort
:按大小排序 -
' [Bb] '
:匹配.bss
段(大写 B 是全局变量,b 是局部静态变量)
示例输出:
20001000 00010000 B big_buffer
20011000 00000004 b static_flag
-
big_buffer
是个大数组,占了 64KB -
static_flag
是局部静态变量,占了 4 字节
方法 3:用 objdump
查看段内容(结构)
objdump -h your_program.elf
输出:
Idx Name Size VMA LMA File off Algn5 .bss 00010000 20001000 20001000 00000000 2**4CONTENTS, ALLOC, LOAD, DATA
显示 .bss
占了 0x10000
(64KB),起始地址 0x20001000
为什么 .bss 很大?
常见原因
-
定义了大型全局/静态数组
char buffer[64 * 1024]; // 占用 64KB
-
某些库(如
newlib
、printf
)内部定义了缓冲区 -
堆栈大小在链接脚本中定义为
.bss
变量__stack = . + 0x8000; // 32KB stack
-
链接脚本中手动分配了大段内存到
.bss
解决建议
-
检查源代码中是否有大数组(尤其是未初始化的)
-
检查链接脚本中是否
.bss
里分配了栈或堆(如_stack_size
) -
使用
nm
/size
排查真正占空间的变量 -
如果你用的是嵌入式系统,考虑是否能用动态内存或精简库(如
nano.specs
)