LD搜索共享库两次并忽略已加载的实例

时间:2018-03-26 13:59:35

标签: c++ linux ld

所以有点历史,我有3个库:

  • " lib1.so"没有依赖
  • " lib2.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);

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"的依赖关系时尽管已经以编程方式加载了它?

1 个答案:

答案 0 :(得分:0)

原因是您的程序不知道在哪里查找lib1.sodlopen加载并将库分配给指针,但这并不是全局工作 - 现在没有为整个程序加载,你只能通过指针显式引用库。

当您自己加载它时,您可以直接加载并提供完整路径,这样您的程序就可以轻松加载。

当您加载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.sodlopen首先尝试解析路径,然后才能解决任何符号问题。