高级C/C++编译技术之读书笔记(二)之库的概念

本节思维导图1.位置无关代码(PIC)首先,需要理解加载域与运行域的概念。加载域是代码存放的地址,运行域是代码运行时的地址。为什么会产生这2个概念?这2个概念的实质意义又是什么呢?在一些场合,

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

                                                                                    高级C/C++编译技术之读书笔记(二)之库的概念

  最近有幸阅读了《高级C/C++编译技术》深受启发,该书深入浅出地讲解了构建过程(编译、链接)中的各种细节,从多个角度展示了程序与库文件或代码的集成方法,提出了面向代码复用和系统集成的软件架构设计方法,以及系统开发过程中疑难问题的解决方案。

  以下将回头记录下其中的关键要点,以便后面查阅。

本节思维导图

高级C/C++编译技术之读书笔记(二)之库的概念

1. 位置无关代码(PIC)

  首先,需要理解加载域与运行域的概念。加载域是代码存放的地址,运行域是代码运行时的地址。为什么会产生这2个概念?这2个概念的实质意义又是什么呢?

  在一些场合,一些代码并不在储存这部分代码的地址上执行地址,比如说,放在norflash中的代码可能最终是放在RAM中运行,那么中norflash中的地址就是加载域,而在RAM中的地址就是运行域。

  在汇编代码中我们常常会看到一些跳转指令,比如说b、bl等,这些指令后面是一个相对地址而不是绝对地址,比如说b main,这个指令应该怎么理解呢?main这里究竟是一个什么东西呢?这时候就需要涉及到链接地址的概念了,链接地址实际上就是链接器对代码中的变量名、函数名等东西进行一个地址的编排,赋予这些抽象的东西一个地址,然后在程序中访问这些变量名、函数名就是在访问一些地址。一般所说的链接地址都是指链接这些代码的起始地址,代码必须放在这个地址开始的地方才可以正常运行,否则的话当代码去访问、执行某个变量名、函数名对应地址上的代码时就会找不到,接着程序无疑就是跑飞。但是上面说的那个b main的情形有点特殊,b、bl等跳转指令并不是一个绝对跳转指令,而是一个相对跳转指令,什么意思呢?就是说,这个main标签最后得到的只并不是main被链接器编排后的绝对地址,而是main的绝对地址减去当前的这个指令的绝对地址所得到的值,也就是说b、bl访问到的是一个相对地址,不是绝对地址,因此,包括这个语句和main在内的代码段无论是否放在它的运行域这段代码都能正常运行。这就是所谓的位置无关代码。

  由上面的论述可以得知,如果你的这段代码需要实现位置无关,那么你就不能使用绝对寻址指令,否则的话就是位置有关了。

2. 静态库的创建

  静态库是通过编译器编译源代码文件并将生成的目标文件打包生成后的归档文件,我们通过名为归档器(archiver)的工具来生成静态库

  $ gcc -c first.c second.c 

  $ ar rcs libstaticlib.a first.o second.o

  ar工具还可以完成以下任务:

  (1)从库文件中删除一个或多个目标文件

  (2)从库文件中替换一个或多个目标文件

  (3)从库文件中提取一个或多个目标文件

3. 丢失符号可见性和唯一性的可能性

  链接器将静态库的节拼接到客户二进制文件,当链接完成后,静态库的节将与客户二进制文件中的原有的目标文件节进行无缝链接,静态库中的符号成为客户二进制文件符号列表中的一部分,并且保留了其原有的可见性,静态库中的全局符号成为客户二进制文件的全局符号,同样地,静态库的局部符号也称为客户二进制文件的局部符号。

  但是,当客户二进制文件是一个动态库时,上面的原则还是不是一样呢?

  动态库的设计原则规定只提供(即接口可见性)满足与外部通信的接口,采用该设计原则最终会影响到静态库符号的可见性,静态库的符号不会作为全局可见的符号保留,而是会变成私有符号或被忽略(即动态库的符号表中没有这个静态库符号)

  另外一个非常重要的特性是:动态库能够完全自主管理其局部符号,实际情况是会有许多动态库被加载到相同的进程中,一个动态库会包含与其它动态库具有相同名称的局部符号,而链接器能够避免命名的冲突。

4. 静态库使用禁忌

(1)当链接一个静态库需要多个动态库时,可能不应该使用静态库,选择使用动态库可能会比较有利

(2)应该使用同一库的已存在的动态库版本

(3)如果你所实现的功能需要存在一个类的单个示例中,最好使用动态库

5. 静态库链接的具体规则

在linux下链接静态库需要遵循下列规则

(1)依次链接静态库,每次一个静态库

(2)链接静态库从传递给连接器的静态库列表的最后一个静态库开始(通过命令或者makefile),且会反方向逐个链接,直到列表中的第一个位置

(3)链接器会对静态库进行详细的检索,在所有的目标文件中,只有包含客户二进制文件实际所需符号的目标文件才会进行链接

  由于这些特定的规则,我们有时需要在传递给链接器的静态列表多次添加同一个静态库,当一个静态库同时提供了多种完全不同的功能时,就会遇到这种多次添加的情况

6. 将静态库转换成动态库

(1)使用打包工具(ar)来提取所有静态库中的目标文件

  $ ar -x <static library>.a

  执行该命令会把静态库中的目标文件集合提取到当前目录

(2)链接器使用提取出来的目标文件集合来构建动态库

7. 静态库在64位linux平台上的问题

  在64位linux平台上使用静态库会遇到一个非常特殊的情况

(1)将静态库链接到可执行文件与在32位linux上进行操作没有任何区别

(2)但是,静态库链接到共享库则要求静态库需要用-fPIC或-mcmodel-large编译器选项来进行构建(编译器在编译过程中的错误打印输出时的建议)

静态库的导入选择条件:当客户端二进制文件链接静态库时不会把整个静态库的内容链接进来,智慧链接目标文件中必要的符号

动态库的导入选择条件:当客户端二进制文件链接动态库时,选择的条件是在符号表这个层面上,只会选择包含在符号表中实际需要的动态库符号,但是在其它所有方面,这个选择条件实际上是不存在的,无论动态库功能中具体需要的代码有多少都会将整个动态库链接进来。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/120110.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 单片机结构_单片机原理读书笔记

    单片机结构_单片机原理读书笔记文章目录Chapter1:51单片机结构1.1MCS-51单片机内部结构1.1.151单片机内部结构1.1.2核心部件CPU1.2存储器1.2.1ROM和RAM1.2.2普林斯顿结构、哈佛结构1.2.3片内存储器、片外存储器1.2.4程序存储器、外部数据、内部数据存储器1.3特殊功能寄存器1.4时钟电路和复位电路1.4.1时钟电路1.4.2基本时序单位1.4.3复位…

  • linux必须运行在enforcing,Linux(入门基础):97—SELinux三种模式的启动、关闭、查看(getenforce、setenforce、sestatus、restorecon)…

    linux必须运行在enforcing,Linux(入门基础):97—SELinux三种模式的启动、关闭、查看(getenforce、setenforce、sestatus、restorecon)…一、SELinux三种模式简介Enforcing:强制模式。代表SELinux在运行中,且已经开始限制domain/type之间的验证关系Permissive:宽容模式。代表SELinux在运行中,不过不会限制domain/type之间的验证关系,即使验证不正确,进程仍可以对文件进行操作。不过如果验证不正确会发出警告Disabled:关闭模式。SELinux并没有实际运行二、getenforce命…

  • 任务调度器有哪些_本地计算机上的task scheduler

    任务调度器有哪些_本地计算机上的task schedulerTaskScheduler可以看做任务调度的客户端,负责任务的提交,并且请求集群管理器对任务调度。TaskScheduler的类UML图如下,针对不同部署方式会有不同的TaskScheduler与SchedulerBackend进行组合。TaskScheduler类负责任务调度资源的分配,SchedulerBackend负责与Driver、Executor通信收集Executor上分配给该应用的资…

    2022年10月11日
  • 画平行线的步骤口诀_长轴的简化画法

    画平行线的步骤口诀_长轴的简化画法平行线的判定方法是初中数学必须要掌握的知识,但有些同学不太熟悉平行线的判定方法,总会出现丢分的现象,我们一起来看一下常用的平行线的判定方法。(1)平行线的定义法在同一平面内,不相交的两条直线叫做平行线。直线a与b平行,则a∥b(2)平行线的传递性如果两条直线都与第三条直线平行,那么这两条直线也互相平行。也就是说:如果b∥a,c∥a,那么b∥c例题:如图,直线a∥b,b∥c,c∥d,那么a∥d吗?…

  • 用js来实现那些数据结构09(集合01-集合的实现)

    说到集合,第一个想到的就是中学学到的那个数学概念:集合。在我们开始集合相关的js实现前,我们有必要来了解一下什么是集合以及集合的数学概念。好吧,我们一起来复习一下早就被我们遗忘的集合。集合是由一组

  • 零基础学Java(13)方法参数

    零基础学Java(13)方法参数前言首先回顾一下在程序设计语言中关于如何将参数传递给方法的一些专业术语。按值调用表示方法接收的是调用者提供的值。而按引调用表示方法接收的是调用者提供的变量地址。方法可以修改按引用传递的变量的值,而不

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号