Skip to content

Commit 409ca3a

Browse files
committed
完善编译连接过程
1 parent 24ac1f7 commit 409ca3a

File tree

1 file changed

+68
-6
lines changed

1 file changed

+68
-6
lines changed

C++/Compiler.md

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ C/C++编译系统将一个程序转化为可执行程序的过程包含:
99
* 汇编(assembly):把汇编语言代码翻译成目标机器指令的过程。
1010
* 链接(linking):找到所有用到的函数所在的目标文件,并把它们链接在一起合成为可执行文件(executable file)。
1111

12+
整个过程如下图所示:
13+
14+
![编译链接过程][1]
15+
1216
# 预处理
1317

1418
预处理器是在程序源文件被编译之前根据预处理指令对程序源文件进行处理的程序。**预处理器指令以#号开头标识,末尾不包含分号**。预处理命令不是C/C++语言本身的组成部分,不能直接对它们进行编译和链接。C/C++语言的一个重要功能是可以使用预处理指令和具有预处理的功能。C/C++提供的预处理功能主要有文件包含、宏替换、条件编译等。
@@ -61,13 +65,64 @@ C/C++编译系统将一个程序转化为可执行程序的过程包含:
6165
* `静态链接`:在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中,程序运行的时候不再需要静态库文件。
6266
* `动态链接`:把调用的函数所在文件模块(DLL)和调用函数在文件中的位置等信息链接进目标程序,程序运行的时候再从DLL中寻找相应函数代码,因此需要相应DLL文件的支持。
6367

64-
这里的库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。库有两种:静态库(.a、.lib)和动态库(.so、.dll),所谓静态、动态是指链接方式的不同。
68+
这里的库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。库有两种:静态库(.a、.lib)和动态库(.so、.dll),所谓静态、动态是指链接方式的不同。**要注意静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。**
69+
70+
## 静态库创建、使用
71+
72+
静态链接库与动态链接库都是**共享代码**的方式。静态库可以简单看成是一组目标文件(.o/.obj文件)的集合,即很多目标文件经过压缩打包后形成的一个文件。静态库特点总结:
73+
74+
* 静态库对函数库的**链接**是放在编译时期完成的,运行时不会再进行链接。
75+
* 程序在运行时与函数库再无瓜葛,移植方便。
76+
* 浪费空间和资源,因为所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件。
77+
* 静态库对程序的更新、部署和发布也会带来麻烦。如果静态库更新了,所有使用它的应用程序都需要重新编译、发布给用户。
78+
79+
Linux下使用ar工具、Windows下vs使用lib.exe,将目标文件压缩到一起创建静态库,并且对其进行编号和索引,以便于查找和检索。Linux下静态库命名一般是"lib[your_library_name].a":lib为前缀,中间是静态库名,扩展名为.a。Linux创建静态库过程如下(大一点的项目会编写makefile文件来生成静态库,输入多个命令太麻烦了):
80+
81+
1. 将代码文件编译成目标文件.o;
82+
2. 通过ar工具将目标文件打包成.a静态库文件;
83+
84+
整个过程如下图:
85+
86+
![静态库生成过程][2]
87+
88+
对于一个静态库,我们还可以使用 ar 命令查看其中的目标文件,如下:
89+
90+
```shell
91+
$ ar -t libhycu.a
92+
  base64.c.o
93+
  binbuf.c.o
94+
  cache.c.o
95+
  chunk.c.o
96+
  codec_a.c.o
97+
```
98+
99+
## 动态库创建、使用
65100

66-
静态链接库与动态链接库都是**共享代码**的方式。如果采用静态链接库,程序在运行时与函数库再无瓜葛,移植方便。但是会浪费空间和资源,因为所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件。此外,静态库对程序的更新、部署和发布也会带来麻烦。如果静态库更新了,所有使用它的应用程序都需要重新编译、发布给用户。
101+
静态库已经达到代码复用的目的,并且容易使用和理解,那为什么还需要动态库呢?因为静态库有着以下的缺点:
67102

68-
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行是才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新。
103+
1. 空间浪费。静态库在内存中可能存在多份拷贝,因为每一个使用了静态库的可执行文件都单独需要在内存中放一份静态库。
104+
2. 静态库对程序的更新、部署和发布会带来麻烦。如果静态库liba.q 更新了,所有使用它的应用程序都需要重新编译、发布给用户(对于玩家来说,可能是一个很小的改动,却导致整个程序重新下载,全量更新)。
69105

70-
此外,还要注意静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。
106+
动态库在程序编译时并不会被链接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行时才被载入,也解决了静态库对程序的更新、部署和发布带来的麻烦。用户只需要更新动态库即可,增量更新。
107+
108+
动态库特点总结:
109+
110+
* 动态库把对库函数的链接载入推迟到程序运行的时期。
111+
* 可以实现进程之间的资源共享。(因此动态库也称为**共享库**
112+
* 将一些程序升级变得简单。
113+
* 甚至可以真正做到链接载入完全由程序员在程序代码中控制(显示调用)。
114+
115+
Linux 下动态链接库的名字形式为 libxxx.so,前缀是lib,后缀名为“.so”。与创建静态库不同的是,不需要打包工具(ar、lib.exe),直接使用编译器即可创建动态库。简单示例如下:
116+
117+
```shell
118+
$ g++ -fPIC -shared -o libdynmath.so DynamicMath.cpp
119+
```
120+
121+
Linux下可以用nm命令查看动态库包含的目标文件,此外还可以用 ldd 命令来查看一个可执行文件需要哪些动态库。可执行文件在执行前,必须知道依赖的动态库的位置。可以通过下面三种方法来告诉可执行文件搜索动态库的位置:
122+
123+
* 将动态库的路径添加到名为 LD_LIBRARY_PATH 的环境变量;
124+
* 把库拷贝到 /usr/lib 和 /lib目录下;
125+
* 修改`/etc/ld.so.conf`文件,把动态库所在的路径加到文件末尾,并执行`sudo ldconfig`刷新。这样,加入的目录下的所有库文件对于可执行程序都是可见的;
71126

72127
# 简单的例子
73128

@@ -123,12 +178,19 @@ helloworld.cpp 的源代码,仅仅有六行,而且该程序除了显示一
123178
➜ ~ ./helloworld.o
124179
hello, world
125180

126-
127181
# 更多阅读
128182

129183
[详解C/C++预处理器](http://blog.csdn.net/huang_xw/article/details/7648117)
130184
[Compiling Cpp](http://wiki.ubuntu.org.cn/Compiling_Cpp)
131185
[C++静态库与动态库](http://www.cnblogs.com/skynet/p/3372855.html)
132186
[高级语言的编译:链接及装载过程介绍](http://tech.meituan.com/linker.html)
133-
[编译原理 (预处理>编译>汇编>链接)](http://www.cnblogs.com/pipicfan/archive/2012/07/10/2583910.html)
187+
[编译原理 (预处理>编译>汇编>链接)](http://www.cnblogs.com/pipicfan/archive/2012/07/10/2583910.html)
188+
[帮 C/C++ 程序员彻底了解链接器](http://blog.jobbole.com/96225/)
189+
[链接库以及编译过程](http://liubigbin.github.io/2016/03/20/%E9%93%BE%E6%8E%A5%E5%BA%93%E4%BB%A5%E5%8F%8A%E7%BC%96%E8%AF%91%E8%BF%87%E7%A8%8B/)
190+
191+
192+
[1]: http://7xrlu9.com1.z0.glb.clouddn.com/C++_Compiler_1.png
193+
[2]: http://7xrlu9.com1.z0.glb.clouddn.com/C++_Compiler_2.png
194+
195+
134196

0 commit comments

Comments
 (0)