所以有点历史,我有3个库:
我执行以下可执行代码:
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);
ptr_lib1有值(这意味着库加载好了),但ptr_lib2值为NULL(!!!),dlerror给我这个:
"lib1.so: cannot open shared object file: No such file or directory"
之后我做了这个:
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
请有人解释我为什么链接器试图加载" lib1.so"在解决" lib2.so"的依赖关系时尽管已经以编程方式加载了它?
答案 0 :(得分:0)
原因是您的程序不知道在哪里查找lib1.so
。 dlopen
加载并将库分配给指针,但这并不是全局工作 - 现在没有为整个程序加载,你只能通过指针显式引用库。
当您自己加载它时,您可以直接加载并提供完整路径,这样您的程序就可以轻松加载。
当您加载lib2.so
时,所有程序都知道该库名为lib1.so
,但不是它所在的位置,因此它可以环顾四周。调试打印中的那些目录是Linux程序知道查看共享库的默认文件夹。要添加非标准区域,可以在运行之前将其添加到LD_LIBRARY_PATH
:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/test
(我假设有一个bash
味道shell)所以当你运行你的程序时,它也知道在那里寻找动态库。
@AlexDepler指出RTLD_GLOBAL
应该make make
此共享对象定义的符号将可用于后续加载的共享对象的符号解析。
(手册页)。但这意味着任何已定义的符号(函数,全局等),但不是我理解的路径。由于您已经链接lib2.so
,dlopen
首先尝试解析路径,然后才能解决任何符号问题。