[音乐] 下面我们继续来讲解符号和符号解析
我们讲过符号解析的目的呢,是为了把符号的引用和符号的定义关联起来
每个定义符号,在代码段和数据段当中呢,都分配了存储空间,这个刚才我们讲过了
引用符号和定义符号建立关联以后呢
从定位的时候就可以把引用符号的地址重定位成相关联的定义符号的地址了
这个就是我们讲符号解析的目的。
是为了解决 引用的符号和定义符号之间的这个关联 引用符号和定义符号之间的关联。
有了这个关联以后,我们就可以进行重定位 本地的局部符号,这边我们举的这个例子
都是本地的,因为是在本地定义,并且在本地引用的
所以解析的时候呢,比较简单,只要把本模块内的唯一定义的符号
和这个引用关联就可以了。
所以难的是全局符号的解析,全局符号是指 在外部定义,在本模块使用的,或者在
内部定义而外部模块使用的这些全局符号 它们的解析涉及到多个模块,所以呢,比较复杂
因此我们首先把全局符号进行一些定义 定义它是强符号还是弱符号,这个我们后面 会介绍。
符号的定义我们前面其实上已经讲过了 实际上是指每一个定义的符号都会分配
一块存储空间,比如说这个符号是一个函数名的话 它的存储空间,存放的就是这个代码
如果这个符号是一个变量名的话,它的存储空间 是实际上就是这个变量所占的静态数据区
比如说变量赋个初值,那么这个初值所占的这个空间,就是这个变量这个符号的存储空间
那么这段存储空间的首地址就是这个符号的值。
这是我们在前面解释符号定义的含义的时候讲过 对于这种全局符号,它当然也有存储空间。
这种 存储空间实际上一定只能有唯一的一个空间
不可能有同一个符号分配两块空间,到时候访问的时候,我到底该访问哪块空间呢?
所以就有问题,因此这个符号的解析也称为 符号的绑定。
所谓绑定就是把应用和定义绑定起来
在绑定的时候,对于符号的这个一个引用,一定是只能引用到唯一的那个定义的那个地方去
如果有多重定义的时候,就会有问题,这个就是我们讲的全局符号后面 要解释的这个问题。
我们先来 看一看全局符号的强弱问题,因为我们前面讲过了局部符号 很简单,剩下来的是全局符号比较麻烦。
那么全局符号 麻烦在哪里呢?是因为它关联到多个模块
因此我们先要确定这个全局符号的强弱特性 什么叫强符号呢?所有的函数名都是强符号,还有
已初始化的全局变量名也是强符号,那么剩下来的就是未初始化的全局变量名 就是弱符号了。
那么很显然在这个里面,这两个模块
构成了一个程序,在这个里面,它的强符号就是这个
这个符号因为它已经初始化了,所以它是一个强符号
所有的函数都是强符号,所以p1和p2都是强符号 而这个变量它没有赋初值
,所以它是弱符号 因此我们可以看到这三个是强符号,这一个是弱符号
在前面给出的这个例子当中,我们来看一下哪些符号是强符号,哪些符号是弱符号
首先这些函数名都是强符号 有初始化值的这些变量名也是强符号
这个也有初始化的变量名是强符号。
而且这些 符号都应该是全局符号,强弱只有全局符号才有
然后呢,弱符号是这个swap,在这个里面它是一个弱符号 因为它仅仅是一个原型声明,然后在
这个里面,它是一个外部符号,所以它也是弱符号 然后这个是没有赋初值的,而且是一个本地的,所以它
不是一个全局符号,加了static了,是一个本地的局部符号
这个地方是引用,它不是一种定义,所以它也没有强弱 符号的问题。
这个是个局部变量,也没有强弱符号的问题 所以这里面的强符号就是这四个。
对于 多重定义符号,它的处理规则是这样的,第一个
在一个程序当中,多个模块当中,所有的 强符号只能定义一次,不能定义多次
否则就是链接错误,这是第一个。
就是链接器首先会去看这个强符号
有没有多次定义,多个强符号定义同一个符号的时候如果有多次
出现的都是强符号的话那么就会有链接错误 第二个规则是如果一个符号被定义为一次强符号
和多次弱符号,那么这个定义就按强定义为准
也就是说,一个符号它定义了多次,从我们前面来讲的话,它就会有占多个存储空间 这个是不允许的。
因此这种情况下我们只能 把所有的这些定义选一个存储空间为准
这个存储空间就是那一次的强符号的那个地方
如果在某一个模块引用了某个弱符号,这个引用实际上是解析成
和那个强定义符号关联,而那个弱符号的那个地方就 无视它,就不管它。
然后第三个规则是 当有多个弱符号定义的时候,任选其中之一
就是说如果某个变量的定义在多个模块当中出现并且呢都没有赋初值,那么这些都是弱符号
这些弱符号选其中一个,如果是选第一次出现的那就选那一个为定义的 符号。
那么如果在这个GCC当中用了这个选项来进行链接的话
这时候链接器会输出一个信息 如果是有多个弱定义的全局符号的时候呢
它就会输出一条警告信息,告诉程序员说你的这个程序
当中出现了一个符号进行了多次的弱定义
这个链接呢也是可以做的,但是它有潜在的一些问题出现,后面我们会举一些例子来说明
那么也就是从上面的规则当中我们可以看出
当一个符号在多个地方进行定义的时候,最终解析的时候
只能有一个确定的定义,也就是每个符号只能在一处存储空间 [音乐]
[音乐]