动态库与静态库
C++的库又被分为两种,静态库,动态库。动态库在C++程序中是经常使用的,一定要理解动态库的工作原理并且会制作它。静态库的使用频率要比动态库低一些,但工作原理和制作流程还是要尽量掌握的。
库的作用
很多时候,一套源代码是非常宝贵的,我们并不想让他人知道实现部分。
可以只给他人提供一个头文件,也就是调用接口。而将实现部分(也就是对应的cpp文件)编译为二进制文件(二进制文件人类无法阅读),实现部分在被编译为二进制文件后,就被称为库。
如果不想让别人修改已经写好的代码,就可以给他人提供已经编译好的库,这样既加快了程序的编译或执行速度,又防止他人修改代码。
C++动态库
cout是ostream类的对象,ostream类的声明部分在iostream中,那ostream的实现部分在哪里呢? 答案是,在C++动态库中。至于动态库究竟是什么,我们实际看一下。
# 编译test
g++ main.cpp add.cpp sub.cpp -o test
# 查看可执行文件所需要的动态链接库
ldd test # 输出libstdc++.so.6 => /lib/x86-64-linux-gnu/libstdc++.so.6
# 查看链接
ls -l libstdc++.so.6 # 输出libstdc++.so.6 => libstdc++.so.6.0.28看到libstdc++.so.6是个软链接 这个软链接指向的才是cpp真正的动态运行库 如果我们要升级cpp版本 我们只需要下载好最新版本的动态运行库 让这个指向新的动态运行库就可以了
动态库
动态库是程序执行时才会连接的库,也就是说,程序如果缺乏动态库,那么仍然是可以编译的,只不过在执行时会出现找不到定义的错误。
每个进程都有动态库链接区,这个区就是存储程序在编译时链接的动态库的。
动态库制作
PIC是 Position Independent Code 的缩写,表示要生成位置无关的代码,这是动态库需要的特性
-shared告诉g++生成动态库而不是可执行文件。
g++ -fPIC -shared fileName.cpp -o libFileName.so
g++ main.cpp -L ./ -l sub -o test动态库使用
动态库的设计理念这样就是将动态库集中在几个目录中,这样方便管理。
比如C++程序常用的io库,stl库就作为动态库存放在固定目录中。
如果通过-L来指定目录,那么容易导致库的存储混乱,带来各种麻烦,比如程序的部署就是个大问题。
于是,进程在加载动态库时,会按照优先级从高到低的顺序在以下路径依次寻找,找不到就报错了。
我们需要把动态库拷贝到那些路径可以找到的地方。
1.在生成可执行文件时指定动态库的存放路径
g++ main.cpp sub.cpp -L ./ -ladd -Wl,-rapt=./ -o test一般不推荐使用,容易导致动态库的存放混乱。知道有这么个方法就可以了。
2.修改环境变量:
export LD_LIBRARY_PATH = $LD_LIBRARY_PATH:libPath这种方法最简单,但只可以作为临时的设置方式。如果修改配置文件使其长期生效当然可以,但这种修改配置文件的方式不推荐,如果大家有兴趣,可以百度一下,非常简单。
3.在/lib,/usr/lib目录中查找动态库。
- 我们直接将动态库复制到这两个目录中当然是可以的。
- 但是/lib目录下存放的动态库大都是系统级别的,比如C++标准库
- 我们自己的动态库一般不会直接拷贝到/lib目录中。
4.在/etc/ld.so.config文件中添加动态库路径
- sudo vim /etc/ld.so.conf
- 在文件最后行添加路径
- 保存并退出文件后再 sudo ldconfig
- 在做项目时,可以在/usr/local下创建一个目录。
- 然后将这个目录添加到/etc/ld.so.config文件中。
这四种方法:3用的最少,1偶尔会用,2,4用的都比较普遍。短期内设置路径就用2,长期设置路径,就用4。
静态库
静态库是在程序编译时就会被整合进最终可执行文件的库。程序如果缺乏静态库,那么根本无法编译,在编译期就会报错。
静态库制作
# 静态库的制作:
g++ -c *.cpp # 将.cpp 文件生成对应的.o文件。
ar rcs libxxx.a *.o # 使用ar工具将多个.o文件生成一个静态库,ar工具是什么,rcs参数什么意思都不用管,这么记住就可以了。
静态库使用
静态库虽然使用频率和动态库比要低一些,但仍然是最好要掌握的,
g++ main.cpp -L./ -lxxx -o test这样最终可执行程序就制作完毕了,因为静态库直接被编译在最终可执行程序中,所以不需要考虑链接路径的问题。
静态库与动态库
使用静态库得到的程序体积要比动态库大很多:
- 静态库是在编译期被整合进可执行程序的,每有一个地方调用静态库,就要将静态库整合进去,所以如果这个库被频繁调用的话,会导致整个可执行文件大的离谱。
- 动态库只有在可执行文件执行时才会被加载,也就是说动态库只加载了一次。
使用动态库的程序在启动时要比静态库慢一些:
- 动态库在执行时才会加载,而静态库在编译时就加载了,所以使用动态库自然会慢一些。
总结:一般我们都使用动态库,比如C++运行库,当然,如果有些程序被加载的次数很少,且比较追求启动时的效率,也可以使用静态库。
