C++开始前篇,深入编译链接(3)

一,COMMON块

      什么是COMMON块,这是一种机制,早期的Fortran没有动态分配空间的机制,程序员必须事先声明它所需要的临时使用空间的大小。Fortran把这种空间叫做COMMON块,当不同的目标文件需要的COMMON块空间大小不一致时,以最大的一块为准。

    关与强弱符号的定义我们已经学习过,简单来说,编译器将未初始化的全局变量的定义作为弱符号处理,已初始化的作为强符号处理。

  多个符号定义类型不一致的几种情况:

                 1,两个或两个以上强符号类型不一致;

          2,有一个强符号,其他的都是弱符号,出现类型不一致;

                 3,两个或两个以上弱符号类型不一致

              第一种情况链接器会直接报错,

              第二种,直接使用强符号,

              第三种哪个类型占用的空间大就使用哪个,

      我们在前节学习过,关于符号所对应的符号表,当时留的一个问题就是为什么global_uninit不跟static_uninit一样都放在.bss段,而是放在了COMMON块,现在是时候解决了。

看下表:

  当编译器将一个编译单元编译成目标文件时,如果该编译单元包含了弱符号,那么该符号最终所占空间的大小此时是未知的,因为有可能其他的编译单元中该符号所占的符号所占的空间比本编译单元该符号所占的空间要大。所以编译器无法在.bss上给该符号分配空间(即无法保存该符号的信息)。但是链接器可以在链接时读取所有目标文件就可以确定弱符号的大小了,所以它可以在最终输出的文件BSS段为其分配空间。

   过程即是 : 未初始化的全局变量-----》COMMON块------》.bss

                                              编译                   链接              

这是链接之后的文件信息:

看最上一行与最下一行,global_uninit和static_uninit终于在一起了!

二,静态库链接

      我们知道不管是在C语言还是在C++中,有很多库文件,比如很简单的输出Hello world程序:

1 #include<stdio.h>
2 int main()
3 {
4     printf("Hello world!
");
5     return 0;        
6 }

 stadio就是C中的一个标准库,除此之外还有stdlib库,string库等等。。。

  在Linux平台下,我们知道,链接器在链接静态库的时候都是以目标文件为单位的。因此,各个功能都是以目标文件来实现的,printf()就在stdio库中的printf.o文件中并且只有这一个函数,strlen()就在string库中的strlen.o文件中并且只有这一个函数。为什么一个目标文件只有一个函数呢,由于运行库有成百上千个函数,数量非常庞大,每个函数独立地放在一个目标文件中可以尽量减少空间的浪费,没有用的就不用添加了。

-------------------------------------------------------------------------------------------------------------------------------------

到这静态链接就差不多就结束了,但是还是得细细细细的揣摩,下节,动态链接继续!

             

  

原文地址:https://www.cnblogs.com/junlinfeizixiao/p/6087008.html