gpt4 book ai didi

gcc - 为什么链接库的顺序有时会导致 GCC 出错?

转载 作者:行者123 更新时间:2023-12-04 19:24:41 25 4
gpt4 key购买 nike

为什么链接库的顺序有时会导致 GCC 出错?

最佳答案

(请参阅此答案的历史以获得更详细的文本,但我现在认为读者更容易看到真正的命令行)。

以下所有命令共享的公共(public)文件

$ cat a.cpp
extern int a;
int main() {
return a;
}

$ cat b.cpp
extern int b;
int a = b;

$ cat d.cpp
int b;
链接到静态库
$ g++ -c b.cpp -o b.o
$ ar cr libb.a b.o
$ g++ -c d.cpp -o d.o
$ ar cr libd.a d.o

$ g++ -L. -ld -lb a.cpp # wrong order
$ g++ -L. -lb -ld a.cpp # wrong order
$ g++ a.cpp -L. -ld -lb # wrong order
$ g++ a.cpp -L. -lb -ld # right order
链接器从左到右搜索,并记录未解析的符号。如果一个库解析了符号,它会使用该库的目标文件来解析符号(在这种情况下,b.o 来自 libb.a)。
静态库相互之间的依赖关系是相同的——首先需要符号的库,然后是解析符号的库。
如果一个静态库依赖于另一个库,而另一个库又依赖于前一个库,则存在一个循环。您可以通过 -( 封闭循环依赖库来解决此问题。和 -) ,如 -( -la -lb -) (您可能需要转义括号,例如 -\(-\) )。然后,链接器会多次搜索这些包含的库,以确保解决循环依赖关系。或者,您可以多次指定库,因此每个库都在另一个之前: -la -lb -la .
链接到动态库
$ export LD_LIBRARY_PATH=. # not needed if libs go to /usr/lib etc
$ g++ -fpic -shared d.cpp -o libd.so
$ g++ -fpic -shared b.cpp -L. -ld -o libb.so # specifies its dependency!

$ g++ -L. -lb a.cpp # wrong order (works on some distributions)
$ g++ -Wl,--as-needed -L. -lb a.cpp # wrong order
$ g++ -Wl,--as-needed a.cpp -L. -lb # right order
这里也一样——库必须遵循程序的目标文件。与静态库相比,这里的不同之处在于您不需要关心库之间的依赖关系,因为动态库自己会整理它们的依赖关系。
一些最近的发行版显然默认使用 --as-needed链接器标志,它强制程序的目标文件位于动态库之前。如果传递了该标志,则链接器将不会链接到可执行文件实际不需要的库(并且它会从左到右检测到这一点)。我最近的archlinux发行版默认不使用这个标志,所以它没有因为没有遵循正确的顺序而出错。
省略 b.so的依赖是不正确的反对 d.so创建前者时。链接 a 时需要指定库然后,但是 a真的不需要整数 b本身,所以不应该关心 b自己的依赖。
如果您错过指定 libb.so 的依赖关系,下面是一个示例。
$ export LD_LIBRARY_PATH=. # not needed if libs go to /usr/lib etc
$ g++ -fpic -shared d.cpp -o libd.so
$ g++ -fpic -shared b.cpp -o libb.so # wrong (but links)

$ g++ -L. -lb a.cpp # wrong, as above
$ g++ -Wl,--as-needed -L. -lb a.cpp # wrong, as above
$ g++ a.cpp -L. -lb # wrong, missing libd.so
$ g++ a.cpp -L. -ld -lb # wrong order (works on some distributions)
$ g++ -Wl,--as-needed a.cpp -L. -ld -lb # wrong order (like static libs)
$ g++ -Wl,--as-needed a.cpp -L. -lb -ld # "right"
如果您现在查看二进制文件有哪些依赖项,您会注意到二进制文件本身也依赖于 libd。 ,而不仅仅是 libb正如它应该。如果 libb,则需要重新链接二进制文件稍后取决于另一个库,如果你这样做的话。如果其他人加载 libb使用 dlopen在运行时(考虑动态加载插件),调用也会失败。所以 "right"真的应该是 wrong也是。

关于gcc - 为什么链接库的顺序有时会导致 GCC 出错?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72250646/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com