dlopen可加载libnvinfer.so.8但无法加载libnvinfer.so.8.5.1的原因
为何dlopen能加载libnvinfer.so.8却无法加载其指向的libnvinfer.so.8.5.1?
问题场景
执行以下代码时,最后一处CHECK断言失败:
int main(int argc, char** argv) { std::string r = ::file::RLocation("tensor_rt/lib"); setenv("LD_LIBRARY_PATH", r.c_str(), 1); std::string filename = "libnvinfer.so.8"; CHECK(std::filesystem::exists(r+"/"+filename)); void * handle = dlopen(filename.c_str(), RTLD_NOW | RTLD_LOCAL); CHECK(handle); filename = "libnvinfer.so.8.5.1"; CHECK(std::filesystem::exists(r+"/"+filename)); handle = dlopen(filename.c_str(), RTLD_NOW | RTLD_LOCAL); CHECK(handle) << dlerror(); }
错误信息:
F20221212 15:23:07.725180 2924123 test.cc:24] Check failed: handle libnvinfer.so.8.5.1: cannot open shared object file: No such file or directory
目标目录内容:
lrwxrwxrwx 1 shshao shshao 19 Dec 12 15:20 libnvinfer.so -> libnvinfer.so.8.5.1 lrwxrwxrwx 1 shshao shshao 19 Dec 12 15:20 libnvinfer.so.8 -> libnvinfer.so.8.5.1 -rwxr-xr-x 1 shshao shshao 487512744 Oct 27 15:37 libnvinfer.so.8.5.1
原因分析
核心是动态链接器对不同命名格式的库文件搜索规则存在差异:
- 对于
libnvinfer.so.8这类仅带主版本号的文件名,动态链接器会严格遵循LD_LIBRARY_PATH设置的路径查找,识别到软链接后自动跟随加载目标文件。 - 对于
libnvinfer.so.8.5.1这类带有完整版本号(主+次+补丁)的文件名,动态链接器会优先搜索系统标准库路径(如/usr/lib、/usr/local/lib),即便设置了LD_LIBRARY_PATH,也不会优先检索你指定的目录——除非该目录已被加入ld.so.conf配置并更新了缓存。
解决方案
- 使用绝对路径加载:将
dlopen的参数改为绝对路径,即dlopen((r + "/" + filename).c_str(), ...),直接指定文件位置,绕开动态链接器的搜索规则。 - 更新动态链接缓存:在设置
LD_LIBRARY_PATH后,执行sudo ldconfig(需root权限);或把tensor_rt/lib路径添加到~/.config/ld.so.conf.d/下的自定义配置文件中,再执行ldconfig,让系统识别该目录的库文件。 - 编译时指定运行路径:编译程序时添加
-Wl,-rpath=/path/to/tensor_rt/lib参数,将目标目录嵌入程序的运行时搜索路径,无需依赖环境变量。
内容的提问来源于stack exchange,提问作者Shuai Shao
相关产品推荐
相关产品推荐

