.bss section 与common section

大家都知道未初始化的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) } 
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值