高级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资源的热修复,就 ...
随机推荐
- js 科学计数法
function convertNum(num_str){ //参数必须为 字符串 //科学计数法字符 转换 为数字字符, 突破正数21位和负数7位的Number自动转换 // 兼容 小数点左边有多位 ...
- 图像运动去模糊(Motion Deblurring)代码
http://blog.csdn.net/qianliheshan/article/details/12853157 http://www.di.ens.fr/~whyte/ Efficient De ...
- jQuery多级联动美化版Select下拉框
在线演示 本地下载
- 实验一 Linux初步认识
遇到的困难和心得体会: 1.在操作过程中,有道作业是建立一个opt/forloutest的文件,而我建立了一个 OPT文件,cd OPT,却显示not a directory,通过阅读<linu ...
- C语言细节注意
前段时间用C语言写了个小的程序,也算是复习了下好久没有用的C语言.也是有好多的坑了,哈哈. 1.C语言的结构体 结构体的命名最好能够做到规范.因为不同的 编译环境下,不是很规范的命名有时候会导致莫名其 ...
- 第三篇:Spark SQL Catalyst源码分析之Analyzer
/** Spark SQL源码分析系列文章*/ 前面几篇文章讲解了Spark SQL的核心执行流程和Spark SQL的Catalyst框架的Sql Parser是怎样接受用户输入sql,经过解析生成 ...
- spring cloud 基本小结
Spring cloud系列十四 分布式链路监控Spring Cloud Sleuth https://blog.csdn.net/hry2015/article/details/78905489 S ...
- Python基础笔记系列二:分支和循环
本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! 分支:即是if-else和if-elif-else语句 循环:即是whil ...
- Search insert position, 查找插入位置
问题描述:给定一个有序序列,如果找到target,返回下标,如果找不到,返回插入位置. 算法分析:依旧利用二分查找算法. public int searchInsert(int[] nums, int ...
- python学习笔记(excel简单操作)
现在的目标是设计一个接口自动化测试框架 用例写在excel里面 利用python自带的pyunit构建 之前已经安装好了处理excel的模块 这次简单的使用下 提前创建好excel文件 “testca ...