前言
硬件程序调试比较看重内存的分布情况,可以通过编译输出文件来分析运行时的数据结构
如有疑问,欢迎指正,谢谢
内存分布图
- 代码段 (Text segment):存放程序执行代码的区域,设计在低地址防止堆栈溢后覆盖现象,嵌入式系统中也就是ROM区
- 初始化数据段(Initialized data segment):简称data段,存放程序中已经初始化全局与初始化静态变量
- 未始化数据段(Uninitialized data segment):简称bss段,存放程序中未初始化全局与未初始化静态变量,该区域会在程序载入时由内核清零
- 栈(Stack):存放局部变量,自动分配与释放,函数调用时进行内存的分配,调用结束时进行释放
- 堆(Heap):动态内存块,主动分配(malloc/realloc),需要手动释放(free);可以使用brk和SBR调整大小
代码论证
1. C源码样列
#include <stdio.h>
int main(void)
{
printf("Memory Test!");
return 0;
}
- 使用GCC编译后,代码段text占用97字节,初始化数据段data为0字节,未初始化数据段bss占用0字节
2. 代码上增加不初始化静态全局变量
#include <stdio.h>
static int a;
int main(void)
{
return 0;
}
- 使用GCC编译后,未初始化数据段bss增加到4字节,刚好是一个整型变量的占用空间
3. 增加全局变量并赋初值
#include <stdio.h>
static int a;
int b = 1;
int c = 2;
int main(void)
{
return 0;
}
- 使用GCC编译后,未初始化数据段bss仍然为4字节,初始化数据段data为8字节
4.分析目标文件
#include <stdio.h>
static int a;
int b;
int c = 1;
int d = 2;
const char *str = {"Memory Test1"};
int main(void)
{
int e = 0;
e += 1;
printf("%s",str);
return 0;
}
通过GCC进行编译,通过objdump指令查看可执行文件
- .text对应的是汇编的指令
- .data数据段对应的就是全局变量c、d,值分别为1与2
- .rodata段存放了Memory Test1字符串常量
- .bss段未打印,不占用目标文件
- 上图中.bss段大小为4,但是代码定义了两个未初始化的变量,这个和编译器具体实现有关系
结论
- BSS段不保存到目标文件中,所以不占用目标文件的任何空间
- 数据段保存到目标文件中
- 局部变量在运行时进行创建