静态库和动态库学习笔记

库是写好的、可以复用的代码,是一种可执行代码的二进制形势,可以被操作系统载入内存执行。库文件是事先编译好的。

编译过程图

静态库和动态库的区别

1、静态库的扩展名一般是".a"或者“.lib”;动态库的扩展名一般为".so"或者".dll"。 

2、静态库在编译时,会直接整合到目标程序中,具体是在链接阶段会将汇编生成的目标文件.o与引用的库一起链接打包到可执行文件中,编译成功的可执行文件可独立运行;而动态库在编译时不会放到链接的目标程序中,即可执行文件无法单独运行,且运行有动态库的可执行文件时,如果不是默认路径则要指定动态库的路径,否则报错。

最本质的区别:是否被编译到可执行程序内部

静态库

静态库与汇编生成的目标文件可以一起链接为可执行文件,那么静态库必定和.o文件格式相似。其实一个静态库可以简单看成是一组目标文件(.o)的集合,即很多目标文件经过压缩打包后形成的一个文件,相对来说,这是浪费空间和资源的,因为所有相关的目标文件与牵连到的函数库被链接合成一个可执行文件。

创建静态库过程

1、首先,将代码编译成目标文件.o

g++ -c math.cpp

要带参数-c , 否则直接就编译成可执行文件了。

2、通过ar工具将目标文件打包成.a静态库文件

ar -crv libmath.a math.o

这样就生成了静态库libmath.a

3、使用静态库时,只要在后面加选项就可以。

g++ main.cpp -L/home/guo/code -lmath

-L : 表示库的路径,所在目录

-l :指定链接时需要的动态库,编译器查找库时候会在给出的名字前面加上lib,后面加上.a或者.so来确定库的名称。

动态库

静态库的问题:

1、空间浪费,

2、静态库对程序的更新、部署和发布会带来麻烦。比如:如果静态库libmath.a更新了,所有使用它的程序都要重新编译、发布。即使是很小的改动,也要去下载整个程序,这显然不是最优解。

动态库在程序编译过程中不会链接到目标程序中,而是在代码运行时,才会被载入,不同的应用程序如果调用相同的库,那么在内存中只要有一份该共享库的实例,规避了空间浪费。且动态库在程序运行时才会被载入,也解决了静态库对程序的更新、发布等问题,用户只需更新相应的动态库即可。

相应地,动态库加载速度比静态库慢,发布程序要提供依赖的动态库。

动态库的特点:

1、动态库可以对一些库函数的链接推迟到程序运行时;

2、可以实现进程之间的资源共享,动态库也称为共享库;

3、将一些程序升级变得简单;

4、甚至可以真正做到链接载入完全由程序员在程序代码中控制

动态库的创建

1、首先生成目标文件,要加编译其选项-fPIC

g++ -fPIC -c DynamicMath.cpp

-fPIC 选项可以创建与地址无关的编译程序,为了能够在多个应用程序之间共享。

2、生成动态库,此时加链接器选项-shared

g++ -shared -o libdynmath.so DynamicMath.o

 因为动态库不使用ar工具,所以两步可以并作一步:

g++ -fPIC -shared -o libdynmath.so DynamicMath.cpp

使用动态库:

g++ TestDynamicLibrary.cpp -L../DynamicLibrary -ldynmath

运行可执行程序a.out后会报错:

显然,程序运行时,找不到所依赖的库的位置。

如何让操作系统找到它:

1、安装在/lib或者/uer/lib目录下,默认目录;

2、如果安装在其他目录,要将其添加到/etc/ld.so.cache文件中(编辑/etc/ld.so.conf文件,加入库文件所在目录的路径,运行ldconfig,该命令会重建ld.so.cache文件)

3、直接加命令LD_LIBRARY_PATH=具体目录

LD_LIBRARY_PATH=./src ./main

动态库的显式调用

之前所有的调用都是隐式调用:指应用程序在编译和链接时将动态库作为依赖项,编译成可执行文件,并在运行时候自动加载动态库。不用手动控制,由操作系统自动管理。

显示调用:应用程序在运行时,使用libloaderapi函数手动加载动态库,并通过GetProcAddress函数获取动态库中的函数地址,然后直接调用该函数。该方法要应用程序手动控制动态库的加载和卸载,通常用于实现特定功能需求或者插件式设计。

g++一些编译选项:

-  -shared :指定生成动态链接库。

-  -static :指定生成静态链接库。

-  -fPIC :表示编译为位置独立的代码,用于编译共享库。目标文件需要创建成位置无关码, 念上就是在可执行程序装载它们的时候,它们可以放在可执行程序的内存里的任何地方。

-  -L. :表示要连接的库所在的目录。

-  -l:指定链接时需要的动态库。编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.a/.so来确定库的名称。

-  -Wall :生成所有警告信息。

-  -ggdb :此选项将尽可能的生成gdb 的可以使用的调试信息。

-  -g :编译器在编译的时候产生调试信息。

-  -c :只激活预处理、编译和汇编,也就是把程序做成目标文件(.o文件) 。

-  -Wl,options :把参数(options)传递给链接器ld 。如果options 中间有逗号,就将options分成多个选项,然后传递给链接程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值