.bss section 与common section

来源:互联网 发布:网络组织 企业家才能 编辑:程序博客网 时间:2024/06/15 23:12

大家都知道未初始化的global变量会被配置在.bss section中。不过在ELF中没有这么简单,ELF多了一个COMMON section专门用来存放未初始化的global变量。怎么会有两个地方都用来存放未初始化的global变量呢?其实是有差别的,以下我们举个例子来说明:

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。

//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这个变量。
当然如果同时定义两个强类型变量的话,Linker就会跟你抗议了。

//test1.c  
int c = 1; //strong type  
 
//test2.c  
int c = 2; //strong type  
test2.o:(.data+0x0): multiple definition of `c' 
test1.o:~/sway/test1.c:4: first defined here 
collect2: ld returned 1 exit status 

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

.bss { *(.bss) *(COMMON) } 
原创粉丝点击