zoukankan      html  css  js  c++  java
  • Chap-4 Section 4.3 COMMON块

    4.3 COMMON块
    如果一个弱符号定义在多个目标文件中,而它们的类型又不同,怎么办?目前的链接器
    类型并不支持符号的类型,即变量类型对于链接器而言是透明的,它只知道一个名字,并
    不知道类型是否一致,那么当我们定义的多个符号类型不一致时,链接器该怎么处理呢?
    主要分三种情况:
    1.两个或者两个以上的强符号类型不一致
    2.有一个强符号,其他都是弱符号,出现类型不一致
    3.两个或者两个以上弱符号类型不一致

    对于第一种情况而言,定义多个强符号本身就是违法的,链接器会报符号多重定义错误,
    链接器处理的就是后两种情况。

    事实上,现在的编译器和链接器都支持一种叫COMMON块的机制,该机制最早来源于Fortan,
    早期的Fortan没有动态分配空间的机制,程序员必须事先声明所需要的临时使用空间的大小,
    Fortan把这种临时空间叫COMMON块,当不同的目标文件需要的COMMON块空间大小不一致时,
    以最大的那块为准。

    现在的链接器在处理弱符号的时候,采用的就是与COMMON块一样的机制,我们以实例来说明
    该机制。
    假设有如下两个c文件:
    //weak-s1.c
    int var;
    void f();
    int main() {
    var = 12;
    f();
    }

    //weak-s2.c
    double var;
    void f() {
    var = 321;
    }

    将这两个c文件链接成为最终的目标文件test,我们用readelf -s test读取目标文件的
    符号表,如图4.2.12所示:


    ***图4.2.12***
    从图中可以看出,变量var的最终大小为8个字节,所在段的下标为25,我们再用readelf -S test
    读取目标文件的段表,如图4.2.13所示,下标为25的段正好是.bss段。


    ***图4.2.13***

    在单个目标文件中,比如在weak-s1.o中,为什么不直接把未初始化的全局变量也当作
    未初始化的局部静态变量一样处理,为它在.bss段分配空间,而是将其标记为一个COMMON
    类型的变量?
    通过了解编译器处理多个弱符号的过程,我们可以知道,当编译器将一个编译单元编译成
    目标文件后,如果该编译单元包含了弱符号,那么该弱符号最终所占空间的大小在此时是
    未知的,因为可能在其他编译单元中,该符号所占的空间比本编译单元该符号所占的空间
    大,所以编译器此时无法为该弱符号在.bss段分配空间,因为所需要的空间大小未知,但是
    链接器在链接过程中可以确定弱符号的大小,因为当链接器读取所有输入目标文件后,任何
    一个弱符号的最终大小都可以确定,所以它可以在最终输出文件的.bss段为其分配空间,
    所以总体来看,未初始化的全局变量最终还是被放在.bss段的。
    比如,我们单独对weak-s1.c编译,然后用readelf -S weak-s1.o查看该目标文件的段表,如
    图4.2.14所示:


    ***图4.2.14***
    图中.bss段的大小为0,由此说明编译单元为未把该未初始化的全局变量放在.bss段。

  • 相关阅读:
    linux系统数据落盘之细节
    不同类型文件“可读写”的含义
    zz存储系统中缓存的三种类型
    library满(磁带紊乱、虚拟机恢复失败)
    TSM日常维护
    入门级磁带机使用方法
    关于 tsm 磁带槽位
    TSM lan-free原理及配置
    TSM中备份(Backup)和归档(Archive)的区别
    指定stg备份 (即指定tape 磁带)
  • 原文地址:https://www.cnblogs.com/miaoyong/p/3508082.html
Copyright © 2011-2022 走看看