COMMNET块
- 之前说过,
.bss
段存放未初始化的变量,不占据实际的文件大小,但是要分配虚拟地址空间,所以我们依然要知道这些未初始化的变量大小是多少,这个时候就存在一个问题 : 我们之前讲过,全局符号存在强符号和弱符号之分,未初始化的全局符号默认为弱符号,并且强弱符号之间存在一定的规则
- 强符号不允许重复定义
- 如果存在一个强符号和多个弱符号,选择强符号
- 如果有多个弱符号,选择占据空间大的
- 并且要知道,我们的编译后的目标文件会产生各自段,但是编译是针对一个文件的,他可以判断该文件的符号是强符号还是弱符号,但是无法判断,链接的时候,别的目标文件是否有重复的强符号和弱符号,如果有重复的情况出现,我们在编译阶段怎么能确认符号占据的空间呢?进而也就无法确定
.bss
占据的虚拟空间是多大了 - 所以,未初始化的静态变量,会直接放入
.bss段中
,因为静态变量是内部符号,编译器不会去处理他,静态变量绝对不会被别的目标文件引用 - 但是,对于未初始化的全局变量,我们无法确定大小,所以先放入.comment段中,但是链接完成后,还是会放入.bss段中,因为链接的时候针对的是多个目标文件,就可以确认全局变量的大小了
- 下图,是未链接时候的目标文件的ELF格式
#include<stdio.h>
int global_init_val = 84;
int global_uninit_val;
__attribute__((section("FOO"))) int global = 42;
int main(){
int init_a = 20;
int uninit_b;
static int static_b = 40;
static int static_c;
return 0;
}
- 注意 : GCC允许我们,把未初始化的全局变量不以COMMENT块的形式处理
int global __attribute__((global_uninit_val))
- 这种情况下,global_uninit_val就成为了一个强符号
- 所以 : 强弱符号与是否初始化没有强制的关系,我们也可以通过设置,让未初始化的全局变量变成强符号,所以,强弱符号的三个规则是最重要的,必须遵守的,而对于是否初始化不要先入为主