所以有点历史,我有3个库:
我需要的是动态加载" lib2.so"在运行期间从" test"通过" dlopen"执行方法。问题是" lib1.so"由于链接器不知道在哪里找到它,因此无法自动加载。
我试图加载" lib1.so"起初就是这样:
void* ptr_lib1 = dlopen("/usr/local/test/lib1.so", RTLD_NOW | RTLD_GLOBAL);
void* ptr_lib2 = dlopen("/usr/local/test/lib2.so", RTLD_NOW | RTLD_GLOBAL);
但由于某种原因,它不起作用,它在调用第二个dlopen(来自dlerror的文本)后给了我错误:
"lib1.so: cannot open shared object file: No such file or directory"
这意味着" lib1.so"试图加载两次:第一次调用dlopen用于" lib1.so",然后第二次调用dlopen用于" lib2.so"。
任何人都可以解释为什么以及如何解决这个问题?请不要建议在启动可执行文件之前修改LD_LIBRARY_PATH。也不建议修改可执行文件的链接器标志。我需要能够在运行时从任何文件夹加载libs。
更新 经过一些研究,我做到了这一点:
LD_DEBUG=all ./test
发现库lib1.so正在尝试加载两次(第一次调用dlopen时,第二次当LD尝试解析lib2.so&#34时的依赖项时):
add /usr/local/test/lib1.so [0] to global scope
opening file=/usr/local/test/lib1.so [0]; direct_opencount=1
...
30031: file=lib1.so [0]; needed by /usr/local/test/lib2.so [0]
30031: find library=lib1.so [0]; searching
30031: search path=./tls/x86_64:./tls:./x86_64:. (RPATH from file ./test)
30031: trying file=./tls/x86_64/lib1.so
30031: trying file=./tls/lib1.so
30031: trying file=./x86_64/lib1.so
30031: trying file=./lib1.so
30031: search cache=/etc/ld.so.cache
30031: search path=/lib64/tls/x86_64:/lib64/tls:/lib64/x86_64:/lib64:/usr/lib64/tls/x86_64:/usr/lib64/tls:/usr/lib64/x86_64:/usr/lib64 (system search path)
30031: trying file=/lib64/tls/x86_64/lib1.so
30031: trying file=/lib64/tls/lib1.so
30031: trying file=/lib64/x86_64/lib1.so
30031: trying file=/lib64/lib1.so
30031: trying file=/usr/lib64/tls/x86_64/lib1.so
30031: trying file=/usr/lib64/tls/lib1.so
30031: trying file=/usr/lib64/x86_64/lib1.so
30031: trying file=/usr/lib64/lib1.so
30031:
30031:
30031: file=/usr/local/test/lib2.so [0]; destroying link map
仍然不明白发生了什么......
UPDATE2。有完整的LD_DEBUG log
注意:还有另一个库lib_other.so,只需忽略它
答案 0 :(得分:1)
当dlopen(3)失败时,您应该使用dlerror(3)来获取有用的信息。
至少代码:
void* ptr_lib1
= dlopen("/usr/local/test/lib1.so", RTLD_NOW | RTLD_GLOBAL);
if (!ptr_lib1) {
fprintf(stderr, "dlopen lib1 failure: %s\n", dlerror());
exit(EXIT_FAILURE);
}
同样适用于其他dlopen
s
请注意,dlerror
正在提供详细的错误消息。如果你不理解,请把它放在你的问题中。
在关联lib1.so
或lib2.so
时,您可能忘记设置一些rpath。或者您需要明确设置LD_LIBRARY_PATH
,或运行ldconfig
阅读Drepper的How To Write Shared Libraries论文了解详情。仔细阅读ld-linux(8)
dlopen
的 lib2
失败,因为找不到其依赖项lib1
。你需要解决这个问题(通过rpath,LD_LIBRARY_PATH
,ldconfig
等......)
您可以在-Wl,-rpath,/usr/local/test/lib1.so
选项等中添加一些lib1
您还可以(更简单地)决定所有共享库都进入/usr/local/lib/
,您将在/etc/ld.so.conf
中提及。然后,您需要在每个库添加后运行ldconfig
。
答案 1 :(得分:0)
此问题的根本原因似乎是lib1.so
NEEDED
为lib2.so
,这是因为您在构建时链接了它。因此,只需在构建时不要链接它 - 在构建lib1
时根本不要提及lib2
。然后,您可以根据需要使用dlopen()
加载它,lib2
将不会尝试单独加载它。
答案 2 :(得分:0)
我有类似的问题,但它确实有效。我只使用“RTLD_LAZY”代替“RTLD_NOW”。
你可以尝试一下。