linux 链接器/加载器搜索顺序
这个问题与编译和动态链接期间查找库的方式有关。
考虑这个小项目:
- 项目
- liba
- a.hpp
- a.cpp
- libb
- b.hpp
- b.cpp
- main.cpp
- liba
a.hpp:
int AAA();
a.cpp:
#include <b.hpp>
int AAA()
{
return BBB();
}
b.hpp:
int BBB();
b.cpp:
int BBB()
{
return 3;
}
main.cpp:
#include "liba/a.hpp"
#include "libb/b.hpp"
int main()
{
AAA();
BBB();
}
libb 编译为:
cd libb; g++ -shared -o libb.so b.cpp
liba 编译为:
cd liba; g++ -I../libb/ -L../libb/ -lb -shared -o liba.so -Wl,-rpath /full/path/to/project/libb/ a.cpp
和 main 编译为:
g++ -Lliba -la -Wl,-rpath /full/path/to/project/liba/main.cpp
编译完成,没有报错,但是执行a.out时,找不到libb.so。
ldd 输出:
ldd ./a.out
linux-gate.so.1 => (0xffffe000)
liba.so => /full/path/to/project/liba/liba.so (0xb780a000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb76ba000)
libm.so.6 => /lib/libm.so.6 (0xb7692000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7672000)
libc.so.6 => /lib/libc.so.6 (0xb750f000)
libb.so => not found
libb.so => /full/path/to/project/libb/libb.so (0xb750c000)
/lib/ld-linux.so.2 (0xb780e000)
请注意,libb.so 出现两次。有一次,动态链接器无法找到该库,有一次又找到了。我假设,在第二种情况下,它使用 liba.so 中嵌入的 rpath。
当然,有多种方法可以解决该问题(例如LD_LIBRARY_PATH,在编译main.cpp时嵌入正确的rpath...),但我更感兴趣的是为什么main.cpp的编译有效,而动态链接却不起作用't。
到目前为止,我假设使用相同的过程来搜索所需的库。我是否遗漏了什么,或者有什么我不知道的隐藏魔法? :)
(在带有 gcc 4.3.4 的 SLED11 盒子上测试。)
This question is related to the way libraries are looked up during compilation and dynamic linking.
Consider this small project:
- project
- liba
- a.hpp
- a.cpp
- libb
- b.hpp
- b.cpp
- main.cpp
- liba
a.hpp:
int AAA();
a.cpp:
#include <b.hpp>
int AAA()
{
return BBB();
}
b.hpp:
int BBB();
b.cpp:
int BBB()
{
return 3;
}
main.cpp:
#include "liba/a.hpp"
#include "libb/b.hpp"
int main()
{
AAA();
BBB();
}
libb is compiled with:
cd libb; g++ -shared -o libb.so b.cpp
liba is compiled with:
cd liba; g++ -I../libb/ -L../libb/ -lb -shared -o liba.so -Wl,-rpath /full/path/to/project/libb/ a.cpp
and main is compiled with:
g++ -Lliba -la -Wl,-rpath /full/path/to/project/liba/ main.cpp
The compilation finishes without error, but when executing a.out, libb.so can't be found.
ldd outputs:
ldd ./a.out
linux-gate.so.1 => (0xffffe000)
liba.so => /full/path/to/project/liba/liba.so (0xb780a000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb76ba000)
libm.so.6 => /lib/libm.so.6 (0xb7692000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7672000)
libc.so.6 => /lib/libc.so.6 (0xb750f000)
libb.so => not found
libb.so => /full/path/to/project/libb/libb.so (0xb750c000)
/lib/ld-linux.so.2 (0xb780e000)
Note, that libb.so occurs twice. One time, the dynamic linker is not able to find the library and one time it is. I assume, that in the second case it uses the rpath embedded in liba.so.
Of course, there are multiple ways to fix that problem (e.g. LD_LIBRARY_PATH, embed the correct rpath when compiling main.cpp...), but I'm more interested in why the compilation of main.cpp works, while the dynamic linking doesn't.
So far I assumed that the same procedure was used for searching the needed libraries. Is there something I'm missing, or some hidden magic I don't know of? :)
(Tested on a SLED11 box with gcc 4.3.4.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
没有隐藏的魔法,但你基本上已经向编译器承诺你将在运行时告诉加载器在哪里可以找到函数,但你没有。从 AAA 调用的 BBB 知道如何到达那里,但从 main 调用的 BBB 不知道。
There's no hidden magic but you've basically promised the compiler that you're going to tell the loader, at run-time, where to find the functions but you haven't. The BBB called from AAA knows how to get there but the BBB called from main does not.