bss段: BSS段(bsssegment)通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。BSS是英文BlockStarted by Symbol的简称。BSS段属于静态内存分配。 特点是:可读写,在系统启动时BSS段会一般都会自动清0。

data段: 数据段(datasegment)通常是指用来存放程序中已初始化的全局变量和静态变量的一块内存区域。数据段属于静态内存分配。

text段: 代码段(codesegment/textsegment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读。

rodata段: 只读数据区, 比如字符串常量和const修饰的变量等.

1
2
3
4
https://blog.csdn.net/farmwang/article/details/75646306
int a = 1; //.data section  
int b = 0; //.bss section  
int c; //COMMON section 

由上面例子可以知道,如果我们把global变量初始化为非0的值,会被放在.data section。如果把global变量初始化为0,会被直接放到.bss section。如果完全没初始化的话就会被放到COMMON section。

为什么要多一个COMMON section呢?其实跟gcc linker的运作有关系。 以上面例子为例,global变量c其实是一个弱类型。也就是说,如果我们在不同的文件中都声明global变量c而没有初始化的话,gcc linker在做linking时后并不会产生error。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
//test1.c  
int c;  

//test2.c  
int c;  

上面例子是完全合法的,我们也可以定义一个强类型来把弱类型盖掉。
//test1.c  
int c;  
//test2.c  
int c;   
//test3.c  
int c = 1; //strong type  

上面例子gcc linker在做linking时候如果读到test1.c中的int c,linker会先把c放到COMMON section中。读到test2.c的c时,因为发现重复定义,所以不会做处理。读到test3.c中的c由于是强类型,因此会把之前在COMMON的c盖掉,在.data section建立一个初始值为1的c。因次最后的结果我们只会在.data section中找到c这个变量,不会在COMMON中看到c这个变量。

由上面这些例子可以知道,COMMON其实主要的用途是用来让linker做merge用的。因此uninitialized的global变量会被暂时放在COMMON section,等Linker做完merge之后再看情况搬到正确的section中,也可能继续留在COMMON section。因为这种特性,大多数embedded project的linker script档都会把COMMON section放在.bss里头。这样当程序启动时可以一并把COMMON也清为0。