动态库链接和加载时的路径搜索优先级
前言
在开发一个新项目时遇到了动态库加载异常的问题,因此在这里记录一下动态库的链接和加载过程中库路径的搜索优先级的相关知识。
动态库的链接
现在有一个
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
:
在链接阶段,设置RPATH或RUNPATH,将库路径硬编码到可执行文件中
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/*
>
默认库路径