在开发一个新项目时遇到了动态库加载异常的问题,因此在这里记录一下动态库的链接和加载过程中库路径的搜索优先级的相关知识。
现在有一个main.o
可重定位目标文件,其中需要用到开源库log4cpp。在链接的时候,我们可以这样链接:
g++ main.o -o a.out -L/path/to/libs -llog4cpp
其中:
-L/path/to/libs
表示链接器去哪个目录下查找库文件。
编译时库搜索优先级:-L指定的路径
> LIBRARY_PATH
>默认库路径
-llog4cpp
表示要链接的库,在链接阶段,链接器一般会按照搜索优先级,从库路径中查找名为liblog4cpp.so
或liblog4cpp.a
的文件进行链接。若不特殊说明,默认优先链接动态库。
在程序开始运行前的加载阶段,动态链接器会读取可执行文件,查找并加载所有必须的动态库。注意此时的搜索路径并不包含/path/to/libs
,因为它只作用于链接阶段。链接器搜索的路径有:LD_LIBRARY_PATH
环境变量,/etc/ld.so.cache
文件,默认库路径(/usr/lib
,/lib
等)。
如果需要从指定的路径加载动态库,则可以使用下述方法:
LD_LIBRARY_PATH
环境变量:在程序运行前设置环境变量,指定动态库的搜索路径:export LD_LIBRARY_PATH=/path/to/runtime_libs:$LD_LIBRARY_PATH
注意,此方法设置环境变量是临时的,一旦终端关闭设置就会失效。若想使其持久化,需要特殊设置,方法包括但不限于:修改.bashrc文件,修改rc.loacl文件。/etc/ld.so.conf
和/etc/ld.so.conf.d/*
配置:-rpath
:g++ main.o -o a.out -L/path/to/libs -llog4cpp -Wl,-rpath,/path/to/runtime_libs
注意若可执行文件中同时包含RPATH和RUNPATH,那么RPATH将会被动态链接器忽略。加载时共享库的搜索优先级为:
RPATH
>LD_LIBRARY_PATH
>RUNPATH
>/etc/ld.so.conf
和/etc/ld.so.conf.d/*
>默认库路径