linux 链接器/加载器搜索顺序

发布于 2024-12-06 15:33:12 字数 1824 浏览 0 评论 0 原文

这个问题与编译和动态链接期间查找库的方式有关。

考虑这个小项目:

  • 项目
    • liba
      • a.hpp
      • a.cpp
    • libb
      • b.hpp
      • b.cpp
    • main.cpp

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

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小帐篷 2024-12-13 15:33:12

没有隐藏的魔法,但你基本上已经向编译器承诺你将在运行时告诉加载器在哪里可以找到函数,但你没有。从 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文