知识积累->目标文件里有什么(2)->解析一段代码

编译一段具有代表性的代码:

int printf(const char *format,...);
int global_init_var=84;
int global_uninit_var;
void func1(int i){
    printf("%d\n",i);
}
int main(void) {
    static int static_var=85;
    int static static_var2;
    int a=1;
    int b;
    func1(static_var+static_var2+a+b);
    return a;
}

我们使用gcc来编译这个文件(参数-c表示只编译不链接

gcc -c main.c

我们的到了一个1K的目标文件(文件大小可能会因为编译器版本及机器平台不同而变化)

我们使用objdump指令查看此目标文件的结构和内容:

我们看到了6段内容:

text即代码段;data即数据段:保存已经初始化的全局变量和已经初始化的局部静态变量(我们之后会实验证明);cstring里面存储的应该是字符串常量(我们之后会实验证明);

后几段我们以后再探究;

我们将分析一下代码段的内容:

contents of section__text就是text数据以16进制打出来的内容,查看结果,可以很明显的看出,里面包含的正是main.c里面的两个函数func1和main;

data段保存的是那些已经初始化的全局静态变量和已经初始化的局部静态变量,在代码中,这种变量一共有两个:global_init_var和static_var;每个变量为int类型,每个4字节,加起来正好8字节。

其值分别是84(16进制表示为54,2进制表示为01010100)和85(16进制为55,2进制表示为01010101);

在调用printf的时候,用到了一个字符串常量“%d\n”它属于一种只读数据,因此被放到了cstring段,它的大小为4字节,恰好是一个指针的长度,可以认为它存储了一个指针;

有观点认为:bss段存储的是未初始化的全局静态变量和未初始化的局部静态变量;

我们开始实验上面说过的结论:

我们修改一下代码:

新增一个字符串常量,新增一个字符串变量:

int printf(const char *format,...);
int global_init_var=84;
int global_uninit_var;
void func1(int i){
    printf("%d\n",i);
}
int main(void) {
    static int static_var=85;
    int static static_var2;
    char *p="Hello,World";//新增字符串常量
    char *q;//新增字符串变量
    int a=1;
    int b;
    func1(static_var+static_var2+a+b);
    return a;
}

我们使用命令行查看相关内容 

我们发现,与上一段相比,cstring段有所增加,增加了8个字节;text段也有所增加,我们需要确认是否只有字符串常量存储到了cstring段而变量没有,我们再修改一下代码,看一下生成的.o文件的相关信息

int printf(const char *format,...);
int global_init_var=84;
int global_uninit_var;
void func1(int i){
    printf("%d\n",i);
}
int main(void) {
    static int static_var=85;
    int static static_var2;
    //char *p="Hello,World";//注释掉新增的字符串常量
    char *q;//新增字符串变量
    int a=1;
    int b;
    func1(static_var+static_var2+a+b);
    return a;
}

我们可以看出,注释掉了定义的字符串常量,cstring的长度恢复到了之前的4字节,虽然有新定义的字符串变量,但是没有影响到cstring段。

因此:cstring里面存储的应该是字符串常量;

我们再调整一下代码,查看一下data字段的内容信息

int printf(const char *format,...);
int global_init_var=84;
int global_init_var0=85;//新增了一个初始化的全局变量
void func1(int i){
    printf("%d\n",i);
}
int main(void) {
    static int static_var=85;
    int static static_var2;
    //char *p="Hello,World";//新增字符串常量
    char *q;//新增字符串变量
    int a=1;
    int b;
    func1(static_var+static_var2+a+b);
    return a;
}

之前,data段的大小是 00000008(16进制),新增了一个初始化的全局变量之后,变成了0000000c(16进制),两者之间之差恰好是4个字节;

我们再修改一下代码,查看一下相关信息:

int printf(const char *format,...);
int global_init_var=84;
int global_init_var0=85;//新增了一个初始化的全局变量
void func1(int i){
    printf("%d\n",i);
}
int main(void) {
    static int static_var=85;
    int static static_var2=85;//新增一个初始化的局部静态变量
    int a=1;
    int b;
    func1(static_var+static_var2+a+b);
    return a;
}

data的长度变成了10(16进制为10,2进制为10000,10进制为16),正好新增了4个字节;

我们再新增一些未初始化的全局静态变量和局部静态变量,查看一下结果:

int printf(const char *format,...);
int global_init_var=84;
int global_init_var0=85;
int global_uninit0;//新增了未一个初始化的全局变量
int global_uninit1;//新增了未一个初始化的全局变量
int global_uninit2;//新增了未一个初始化的全局变量
void func1(int i){
    printf("%d\n",i);
}
int main(void) {
    static int static_var=85;
    int static static_var2=85;
    int static static_var3;//新增一个未初始化的局部静态变量
    int static static_var4;//新增一个未初始化的局部静态变量
    int a=1;
    int b;
    func1(static_var+static_var2+a+b);
    return a;
}

data段没有变化;

因此:data(即数据段):保存已经初始化的全局变量和已经初始化的局部静态变量;

我们修改一下代码,研究一下bss段

int printf(const char *format,...);
int global_init_var=84;
int global_init_var0=85;
//int global_uninit0;//新增了未一个初始化的全局变量
//int global_uninit1;//新增了未一个初始化的全局变量
//int global_uninit2;//新增了未一个初始化的全局变量
void func1(int i){
    printf("%d\n",i);
}
int main(void) {
    static int static_var=85;
    int static static_var2=85;
    //int static static_var3;//新增一个未初始化的局部静态变量
    int static static_var4;//新增一个未初始化的局部静态变量
    int a=1;
    int b;
    func1(static_var+static_var2+a+b);
    return a;
}

编译,查看相关信息:

我们可以看出,未初始化的静态局部变量会被放在bss段中

我们再修改一下代码,查看相关信息

int printf(const char *format,...);
int global_init_var=84;
int global_init_var0=85;
int global_uninit0;//新增了未一个初始化的全局变量
//int global_uninit1;//新增了未一个初始化的全局变量
//int global_uninit2;//新增了未一个初始化的全局变量
void func1(int i){
    printf("%d\n",i);
}
int main(void) {
    static int static_var=85;
    int static static_var2=85;
    //int static static_var3;//新增一个未初始化的局部静态变量
    int static static_var4;//新增一个未初始化的局部静态变量
    int a=1;
    int b;
    func1(static_var+static_var2+a+b);
    return a;
}

bss段没有变化!!!说明,未初始化的全局静态变量并没有存储在bss段,有些资料(如《程序员的自我修养》)中的观点,Linux操作系统将未初始化的全局静态变量也存储在bss段,但是mac并未遵循这一规则!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章