动态库与静态库
库
什么是库
- 库文件是一种代码仓库,提供给使用者一些可以直接使用的类,函数,变量
- 库是一种特殊的程序,只是不能单独运行
库的好处
- 代码保密
- 方便分发和部署
静态库
静态库的制作
命名规则
Linux下
libxxx.a
lib为固定前缀 xxx为库名 .a为固定后缀
Windows下
libxxx.lib
制作
- gcc获得.o文件
- 使用ar工具(archive)进行打包 ar rcs libxxx.a xxx.o xxx.o
举例
有一个头文件calc.h和四个cpp文件add.cpp sub.cpp divide.cpp multi.cpp 分别实现了四则运算,想要将这些文件打包成一个库文件
gcc -c add.cpp sub.cpp divide.cpp multi.cpp将四个文件编译成.o文件(不需要加入calc.h,因为其在预编译时已经加入其中)
执行这一步后,文件夹内会出现编译完成但没有链接的可执行程序 add.o sub.o divide.o multi.oar rcs libcalc.a add.o sub.o divide.o multi.o
打包成静态库
静态库的使用
首先,要把库和其头文件给出,库文件为实现,头文件说明解释库文件

对于这样一个目录,如果直接执行g++ main.cpp -o app则会报错:
main.cpp:2:10: fatal error: head.h: No such file or directory
2 | #include "head.h"
| ^~~~~~~~
这是由于默认的include路径为当前目录,而head.h文件存在在./include/路径下
解决办法:
- 将头文件拿到该目录下
- -I指令
g++ main.cpp -o app -I ./include
使用上述解决办法后则会再次报错
/usr/bin/ld: /tmp/ccjIQ55y.o: in function
main': main.cpp:(.text+0x58): undefined reference toadd(double, double)'
/usr/bin/ld: main.cpp:(.text+0xbd): undefined reference tomulti(double, double)' /usr/bin/ld: main.cpp:(.text+0x122): undefined reference tosub(double, double)'
/usr/bin/ld: main.cpp:(.text+0x187): undefined reference to `divide(double, double)'
collect2: error: ld returned 1 exit status
函数未定义的引用,即虽然提供头文件,但是并没有相应的实现/定义
解决办法:
g++ main.cpp -o app -I ./include -L ./lib/ .l calc
通过-L指定库的路径 -l指定库名
执行后,生成app可执行文件,运行后
root@VM-12-11-ubuntu:~/cpp/lesson05/library# ./app
a+b=32
a*b=240
a-b=8
a/b=1.66667
完成静态库的使用
动态库
静态库的制作
命名规则
Linux下
libxxx.so
lib为固定前缀 xxx为库名 .so为固定后缀
Windows下
libxxx.dll
制作
- gcc获得.o文件得到和位置无关的代码(-fpic)
g++ -c -fpic a.cpp b.cpp - gcc得到动态库
g++ -shared a.o b.o -o libxxx.so
举例:
有一个头文件calc.h和四个cpp文件add.cpp sub.cpp divide.cpp multi.cpp 分别实现了四则运算,想要将这些文件打包成一个库文件
g++ -c **-fpic** add.cpp sub.cpp divide.cpp multi.cpp一定要写fpic 不然会报错
关于fpic的原理
https://www.cnblogs.com/Linux-tech/p/13873886.html
https://www.cnblogs.com/Przz/p/6505917.html
执行后生成.o文件g++ -shared *.o -o libcalc.so*.o为通配符
执行后得到libcalc.so
和静态库同理,得到如下结构
├── include
│ └── head.h
├── lib
│ └── libcalc.so
├── main.cpp
└── src
├── add.cpp
├── divide.cpp
├── multi.cpp
└── sub.cpp
如果此时执行g++ main.cpp -o app -I ./include -L ./lib/ .l calc
得到可执行程序app后运行
则会报错:
./app: error while loading shared libraries: libcalc.so: cannot open shared object file: No such file or directory
此处涉及动态库的加载原理
动态库加载原理
- gcc链接时,动态库的代码不会被加载到库中
- 程序启动后通过ldd(list dynamic dependency)命令检查动态库依赖关系
root@VM-12-11-ubuntu:~/cpp/lesson06/library# ldd app
linux-vdso.so.1 (0x00007fff699cb000)
libcalc.so => not found
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f4af1a5d000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4af1835000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f4af174e000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4af1c96000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f4af172e000)
- 如何定位动态库文件呢?
动态载入器:对于elf格式的可执行程序,是由ld-linux.so完成,它先后搜索DT_RPATH段->环境变量LD_LIBRARY_PATH段->/etc/ld.so.cache文件列表->/lib , /usr/lib目录找到库文件后将其载入内存
而这里,动态载入器找完以上目录后没有找到所需的libcalc.so动态库,因此报错no such file
解决办法:将动态库文件路径加入以上四个路径其中之一
- 配置环境变量
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/root/cpp/lesson06/library/lib冒号后面为lib的绝对路径
但是这种做法,并不是永久改变,需要写入文件
- 用户级别
- 系统级别
静态库与动态库的区别
静态库在程序的链接阶段被复制到程序中,而动态库是在程序运行时由系统加载到内存中进行调用
静态库
优点
- 移植方便
- 打包到应用程序中,加载速度快
缺点
- 消耗系统资源,浪费内存
- 更新麻烦
动态库
优点
- 可以实现进程间资源共享
- 更新部署发布简单
- 可以控制何时加载动态库
缺点
- 加载速度慢
- 发布程序时需要提供动态库

浙公网安备 33010602011771号