linux上静态库和动态库的编译和使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhang_yin_liang/article/details/85417196

一、linux上静态库和动态库的编译和使用

1.1 特点

动态库特点:

        1、库的代码不会编译进程序里面,所以动态库编译的程序比较小。

         2、由动态库编译的程序依赖于系统的环境变量有没有这个库文件,没有则运行不了。

静态库特点:

        1、库的代码会编译进程序里面,所以静态库编译的程序比较大

        2、由静态库编译的程序不用依赖于系统的环境变量,所以环境变量有没有这个库文件,也可以运行。

参考地址

https://www.cnblogs.com/Harley-Quinn/p/6360363.html

https://blog.csdn.net/nanfeibuyi/article/details/81203021

二、调试

查看linux静态库*.a中或者动态库中的函数和文件,这对某些时候是非常有用的。

2.1 nm

1、可以通过shell脚本去遍历查看动态库中链接的符号。

nm -g --defined-only libxxx.a

2、可以和 grep 命令 配合使用。

nm  *  ·|grep  函数名称。

例如:nm -A /usr/lib/* 2>/dev/null | grep "T memset"

在 /usr/lib/ 目录下找出哪个库文件定义了memset函数. 

参考地址:https://www.cnblogs.com/bonelee/p/6524322.html

2.2 objdump

objdump是gcc工具,用来查看编译后目标文件的组成。

我们在 Linux 下运行一个程序,有时会无法启动,报缺少某某库。这时需要查看可执行程序或者动态库中的符号表,动态库的依赖项, Linux 有现成的工具可用:objdump 。

例如:objdump -x xxx.so | grep "NEEDED" 

参考地址:https://blog.csdn.net/tao546377318/article/details/51727696

2.3 其他技巧

可以通过命令ar查看静态库编译了那些.o文件

ar t libxxx.a

ldd命令可以查询程序运行时需要的依赖库

三、库的依赖问题

为什么会有库的依赖问题?

   一、静态库解析符号引用:

      链接器ld是如何使用静态库来解析引用的。在符号解析阶段,链接器从左至右,依次扫描可重定位目标文件(*.o)和静态库(*.a)。

   在这个过程中,链接器将维持三个集合:

   集合E:可重定位目标文件(*.o文件)的集合。

   集合U:未解析(未定义)的符号集,即符号表中UNDEF的符号。

   集合D: 已定义的符号集。

   初始情况下,E、U、D均为空。

   1、对于每个输入文件f,如果是目标文件(.o),则将f加入E,并用f中的符号表修改U、D(在文件f中定义实现的符号是D,在f中引用的符号是U),然后继续下个文件。

   2、如果f是一个静态库(.a),那么链接器将尝试匹配U中未解析符号与静态库成员(静态库的成员就是.o文件)定义的符号。如果静态库中某个成员m(某个.o文件)定义了一个符号来解析U中引用,那么将m加入E中,

   同时使用m的符号表,来更新U、D。对静态库中所有成员目标文件反复进行该过程,直至U和D不再发生变化。此时,静态库f中任何不包含在E中的成员目标文件都将丢弃,链接器将继续下一个文件。

   3、当所有输入文件完成后,如果U非空,链接器则会报错,否则合并和重定位E中目标文件,构建出可执行文件。

 到这里,为什么会有库的依赖问题已经得到解答:

 因为libchild.a依赖于libbase.a,但是libbase.a在libchild.a的左边,导致libbase.a中的目标文件(*.o)根本就没有被加载到E中,所以解决方法就是交换两者的顺序。当然也可以使用-lbase -lchild -lbase的方法。

参考地址:https://cloud.tencent.com/developer/article/1343895

猜你喜欢

转载自blog.csdn.net/zhang_yin_liang/article/details/85417196