动态链接库

目录

编译时头文件的搜寻路径

gcc在编译时按照如下顺序寻找所需要的头文件:

1.先搜索当前目录( 这里注意,只有用#include "headfile.h"时才会搜索当前目录 )
2.接着搜索-I(大写i)指定的目录
3.然后找gcc的环境变量 C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH
4.再找内定目录: /usr/include, /usr/local/include
5.最后找gcc的一系列自带目录

链接时动态库或静态库的搜寻路径

gcc在编译时按照如下顺序寻找所需要的库文件:

  1. gcc会去找-L指定的目录
  2. 再找gcc的环境变量LIBRARY_PATH
  3. 再找内定目录/lib 和 /usr/lib

这里有两个问题:

1.默认情况下,gcc编译时只会查找相应的头文件,而不会连接具体的lib。也就是说只要include设置完全,就可以编译通过。它没有进一步检查include中的类和函数有没有实现,而是在运行时才开始查找。所以就会经常发生编译可以通过,但运行时却无法运行,因为在运行时它找不到相关类或者函数的实现。

这时,使用-Wl,–no-undefined参数,如果使用了include文件,连接器却找不到相应的实现,就会产生错误提示。

2.编译时默认不查找当前目录,需要使用-L ./指定,例如

运行时动态库的搜寻路径

现代连接器在处理动态库时将链接时路径(Link-time path)和运行时路径(Run-time path)分开,用户可以通过-L指定连接时库的路径,通过-R(或-rpath)指定程序运行时库的路径,大大提高了库应用的灵活性。

只有动态库so文件才需要考虑运行时的加载。 动态库经常因为路径的原因导致无法加载的错误,这使得动态库使用起来相对比较麻烦些,但是它的优势也很明显:编译时不需要真正链接到可执行文件里面。这样意味着,每次动态库升级,不需要重新编译可执行文件,只需要把升级后的so文件拷贝到正确的加载路径即可。

其加载优先顺序为:

  1. -L指定的动态库搜寻路径(通常不好使。 毕竟嵌入式环境中,编译和运行平台完全不一样)

  2. 环境变量LD_LIBRARY_PATH指定的动态库搜寻路径

  3. /etc/ld.so.conf 里面添加动态库搜索路径,记得要执行ldconfig来生效。

  4. 默认系统运行库搜索路径 /lib 或 /usr/lib

注意:

1.动态库搜寻路径并不包括当前目录,所以当即使可执行文件和其所需的so文件在同一文件夹,也会出现找不到问题

2.一般不推荐直接修改环境变量,而是修改/etc/ld.so.conf,将相应的路径添加上,然后ldconfig一下就好

3.ldconfig做的这些东西都与运行程序时有关,跟编译时一点关系都没有,编译的时候还是该加-L就得加,不要混淆了

4.往/lib和/usr/lib里面lib,是不用修改/etc/ld.so.conf的,但是完了之后要调一下ldconfig(很重要),不然这个lib会找不到。而往其他目录加lib,需要修改/etc/ld.so.conf,并且要ldconfig一下。

5.如果确实需要改环境变量,则有以下几种情况:

临时修改(关闭shell后失效):若是权限不够(无法更改/etc/ld.so.conf)或只是想临时改一下环境变量用于测试,则可以使用export,就是export一个全局变量LD_LIBRARY_PATH,然后运行程序的时候就会去这个目录中找lib。如:命令行执行:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/user/abc/lib

一般来讲这只是一种临时的解决方案,在没有权限或临时需要的时候使用。

修改作用于当前用户:在.bashrc中设置或者在./bash_profile设置,这对当前用户生效。记得source ~/.bashrc或source ~/.bash_profile

修改作用于所有用户:在/etc/profile中设置或在/etc/profile.d/中创建一个自定义的shell(**.sh)脚本,一般推荐使用后者。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值