ELF中的.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) }
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
