C++动态库和静态库的特点及编译使用

1 库的概念?

库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库。

2 动态库与静态库的概念?

先回顾一下编译过程:


2.1 静态库

静态库在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中,对应的链接方式称为静态链接。试想一下,静态库与汇编生成的目标文件(.o文件)一起链接为可执行文件,那么静态库必定跟.o文件格式相似。其实一个静态库可以

简单看成是一组目标文件(.o/.obj文件)的归档集合,即很多目标文件经过压缩打包后形成的一个文件。静态库特点总结:

1、静态库对函数库的链接是放在编译时期完成的。
2、程序在运行时与函数库再无瓜葛,移植方便。
3、浪费空间和资源,因为所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件。


除了上面提到的浪费空间和资源的弊端,使用静态库还有另一个问题:对程序的更新、部署和发布页会带来麻烦。如果静态库libtest.a更新了,所有使用它的应用程序都需要重新编译、发布给用户。


2.2 动态库

使用动态库正好可以有效解决静态库的这些问题:动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行是才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新。


3 动态库的创建和使用

我们编写了一个string类型接口的测试程序,工程中包含mystring.cpp mystring.h mystring_test.cpp三个源文件,以及工程的makefile文件

3.1 创建libstring.so动态库

"g++ -shared mystring.cpp mystring.h -o libstring.so"编译生成动态库,但是报了如下错误:

"g++ mystring.cpp mystring.h -fPIC -shared -o libstring.so"成功编译生成动态库:

【注:PIC参数告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。共享对象可能会被不同的进程加载到不同的位置上,如果共享对象中的指令使用了绝对地址、外部模块地址,那么在共享对象被加载时就必须根据相关模块的加载位置对这个地址做调整,也就是修改这些地址,让它在对应进程中能正确访问,而被修改到的段就不能实现多进程共享一份物理内存,它们在每个进程中都必须有一份物理内存的拷贝。fPIC指令就是为了让使用到同一个共享对象的多个进程能尽可能多的共享物理内存,它背后把那些涉及到绝对地址、外部模块地址访问的地方都抽离出来,保证代码段的内容可以多进程相同,实现共享。

3.2 在测试程序中使用动态库

工程的makefile如下:

【注:-L参数指定动态库路径,-l参数动态链接】
用"ldd mystring"查看这个可执行文件的动态链接情况,发现libstring.so这个动态库找不到,是因为链接时链接器(dynamic linker)找到了动态库libstring.so,但动态加载器(dynamic loader, 一般是/lib/ld-linux.so.2)却没找到。

在运行可执行mystring可执行文件时就报错了:
linux为我们提供了两种解决方法:
1.可以把当前动态库路径加入/etc/ld.so.conf中然后运行ldconfig,或者以当前路径为参数运行ldconfig(要有root权限才行)。
2.把当前路径加入环境变量LD_LIBRARY_PATH中
我们这里使用export命令直接将当前路径导入环境变 量LD_LIBRARY_PATH,然后运行程序,运行成功

4 静态库的创建和使用

4.1 创建动态库

先编译生成目标文件,如下图,其中的mystring.o是目标文件

将目标文件归档创建成静态库(libmystring.a)

4.2 使用静态库

修改工程makefile:

与动态链接编译命令相比较,静态链接编译命令只是多了"-static"参数,Linux默认链接动态库,加了static参数就会链接静态库
5 看一下使用动态库链接的方式和静态链接的方式生成的程序有什么差别:
动态链接方式:

静态链接方式:

很明显,动态链接方式生成的可执行文件比静态链接方式生成的可执行文件将占用更少的内存。

猜你喜欢

转载自blog.csdn.net/u012299594/article/details/53048859