高级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编译器选项来进行构建(编译器在编译过程中的错误打印输出时的建议)
静态库的导入选择条件:当客户端二进制文件链接静态库时不会把整个静态库的内容链接进来,智慧链接目标文件中必要的符号
动态库的导入选择条件:当客户端二进制文件链接动态库时,选择的条件是在符号表这个层面上,只会选择包含在符号表中实际需要的动态库符号,但是在其它所有方面,这个选择条件实际上是不存在的,无论动态库功能中具体需要的代码有多少都会将整个动态库链接进来。
高级C/C++编译技术之读书笔记(二)之库的概念的更多相关文章
- 高级C/C++编译技术之读书笔记(一)之编译/链接
最近有幸阅读了<高级C/C++编译技术>深受启发,该书深入浅出地讲解了构建过程(编译.链接)中的各种细节,从多个角度展示了程序与库文件或代码的集成方法,提出了面向代码复用和系统集成的软件架 ...
- 高级C/C++编译技术之读书笔记(三)之动态库设计
最近有幸阅读了<高级C/C++编译技术>深受启发,该书深入浅出地讲解了构建过程(编译.链接)中的各种细节,从多个角度展示了程序与库文件或代码的集成方法,提出了面向代码复用和系统集成的软件架 ...
- 高级C/C++编译技术之读书笔记(四)之定位库文件
最近有幸阅读了<高级C/C++编译技术>深受启发,该书深入浅出地讲解了构建过程(编译.链接)中的各种细节,从多个角度展示了程序与库文件或代码的集成方法,提出了面向代码复用和系统集成的软件架 ...
- 高级C/C++编译技术之读书笔记(五)之动态库版本控制
最近有幸阅读了<高级C/C++编译技术>深受启发,该书深入浅出地讲解了构建过程(编译.链接)中的各种细节,从多个角度展示了程序与库文件或代码的集成方法,提出了面向代码复用和系统集成的软件架 ...
- 深入理解linux网络技术内幕读书笔记(二)--关键数据结构
Table of Contents 1 套接字缓冲区: sk_buff结构 1.1 网络选项及内核结构 1.2 结构说明及操作函数 2 net_device结构 2.1 MTU 2.2 结构说明及操作 ...
- Struts2技术内幕 读书笔记二 web开发的基本模式
最佳实践 在讨论基本模式之前,我们先说说一个词:最佳实践 任何程序的编写都得遵循一个特定的规范.这种规范有约定俗称的例如:包名全小写,类名每个单词第一个字母大写等等等等;另外还有一些需要我们严格遵守的 ...
- webkit技术内幕读书笔记 (二、三)
可视区和网页 通常网页比屏幕的可视区面积要大,因此当网页内容在可视区中放不下时,一般浏览器会提供滚动条. 从URL到构建完DOM树的过程 当用户输入网页URL的时候,WebKit调用其资源加载器加载该 ...
- 深入探索Android热修复技术原理读书笔记 —— 代码热修复技术
在前一篇文章 深入探索Android热修复技术原理读书笔记 -- 热修复技术介绍中,对热修复技术进行了介绍,下面将详细介绍其中的代码修复技术. 1 底层热替换原理 在各种 Android 热修复方案中 ...
- 深入探索Android热修复技术原理读书笔记 —— 资源热修复技术
该系列文章: 深入探索Android热修复技术原理读书笔记 -- 热修复技术介绍 深入探索Android热修复技术原理读书笔记 -- 代码热修复技术 1 普遍的实现方式 Android资源的热修复,就 ...
随机推荐
- E-R图和数据库的设计
数据库设计: 原则:如果属性有了多个字段,可以当实体.如果只有一个字段,只能当属性(比如实体属性种类) 1.设计E-R图 实体:矩形 关系:菱形 属性:椭圆(可省) 2.关系的类型 一对一 一对多 多 ...
- ubuntu16.04 虚拟机 安装win7/win10
http://www.xitongcheng.com/jiaocheng/xtazjc_article_26588.html https://blog.csdn.net/sunyao_123/arti ...
- React Native 网络请求封装:使用Promise封装fetch请求
最近公司使用React作为前端框架,使用了异步请求访问,这里做下总结: React Native中虽然也内置了XMLHttpRequest 网络请求API(也就是俗称的ajax),但XMLHttpRe ...
- no matching key exchange method found. Their offer: diffie-hellman-group1-sha1
1. 使用git克隆项目报错 $ git clone ssh://liuchao@192.168.7.32:29418/platform/Midou Cloning into 'Midou'... U ...
- AJAX基础知识点——思维导图
如图 思维导图图片链接 http://www.edrawsoft.cn/viewer/public/s/4db2e712070147 有道云笔记链接 http://note.youdao.com/no ...
- Merge k Sorted Lists, k路归并
import java.util.Arrays; import java.util.List; import java.util.PriorityQueue; /* class ListNode { ...
- win7 vmware虚拟机上网设置
1.上网方式设成HOST-ONLY 2.将主机的网络共享VMnet1(完成第一步设置后,VMware自动分配虚拟网络VMnet1) 3.win7下查看VMnet1网络ip 4.根据3查看的IP地址在v ...
- 栈的基本操作--java实现
package com.wyl.linklist; /** * 栈的定义及相关操作 * 用数组实现栈 * 栈是一个线性表,不过进栈和出栈操作在表尾操作 * @author wyl * */ publi ...
- D3.js学习笔记(三)——创建基于数据的SVG元素
目标 在这一章,你将会使用D3.js,基于我们的数据来把SVG元素添加到网页中.这一过程包括:把数据绑定到元素上,然后在使用这些元素来可视化我们的数据. 注意:不同于前几章,我们从一个完整的代码开始, ...
- selenium学习笔记(HTMLTestRunner测试报告)
之前提到selenium加入unittest框架.可以引入HTMLTestRunner扩展.以此来生成测试报告 首先是分享下载的百度云地址 http://pan.baidu.com/s/1pKUItW ...