10

除了更长的编译时间之外,链接未使用的库是否有任何缺点?

例如,通过以下两种方式之一编译的程序的可执行文件是否有任何区别:

g++ -o main main.cpp
g++ -o main main.cpp -llib1 -llib2 -llib3 -lmore

*实际上不需要任何库文件来构建 main。

我相信这没有什么区别,因为文件大小相同,但我要求确认。

4

4 回答 4

14

这取决于。

  1. 如果liblib1.aliblib2.aliblib3.a是静态库,并且没有使用其中的符号,那么就没有区别。

  2. 如果liblib1.soliblib2.soliblib3.so是共享库,那么无论是否使用它们,它们都将在运行时加载。您可以使用链接器标志--as-needed来更改此行为,建议使用此标志。

要检查您的二进制文件在运行时直接加载哪些共享库,您可以在 ELF 系统上使用readelf.

$猫main.c
主函数()
{
    返回0;
}
$ gcc main.c
$ readelf -d a.out | 需要 grep
 0x0000000000000001(需要)共享库:[libc.so.6]
$ gcc -lpng main.c
$ readelf -d a.out | 需要 grep
 0x0000000000000001(需要)共享库:[libpng12.so.0]
 0x0000000000000001(需要)共享库:[libc.so.6]

您可以在我的系统上看到,无论是否实际使用了来自它的符号的-lpng链接。链接器标志修复了这个问题libpng12.so.0--as-needed

$ gcc -Wl,--根据需要 -lpng main.c
$ readelf -d a.out | 需要 grep
 0x0000000000000001(需要)共享库:[libc.so.6]

笔记

  1. --as-needed标志必须在库之前指定。它只影响出现在它之后的库。所以gcc -lpng -Wl,--as-needed行不通。

  2. ldd命令不仅列出了您的二进制文件直接链接的库,还列出了所有间接依赖项。这可能会根据这些库的编译方式而改变。只会readelf向您显示您的直接依赖关系,并且只会ldd向您显示间接依赖关系。

于 2012-12-21T04:44:06.357 回答
0

这取决于您是链接静态库还是共享库。如果您正在链接静态库,那么可执行文件的大小会随着每次添加而增加。链接到共享库,不会大大增加可执行文件的大小,只是添加了库符号。

于 2012-12-21T04:45:51.787 回答
0

绝对没错。不利的一面是其他人(或将来的您)会认为出于某种原因需要这些库。大多数人不会花时间减少程序的依赖关系,因此它们的列表会越来越多。

成本与编译代码无关,而与维护和移植程序有关。

于 2012-12-21T04:46:34.123 回答
0

上面有一些非常好的答案。进一步的说明是“它真的有什么不同”。已经提到了维护成本(例如,当有人安装没有 Lib3 的新操作系统时出现问题,因此用户必须去某个地方找到 lib3 并安装它,因为 lib3 也需要 lib17,而您也不需要安装,它为用户增加了更多的工作)。

但是,当你加载二进制文件时,如果你链接到了实际上没有使用的共享库,系统仍然会去寻找那些库,如果它们不存在则拒绝加载——这会增加时间,并安装噩梦.

加载代码后,它应该没有额外的运行时损失。

话虽如此,有时还是有关于链接未使用库的论据。假设您的代码有一个选项 USE_FOO,其中 FOO 功能仅在构建时基于一些任意选择才包含(例如“这是在 Linux 内核 > 3.0 上”或“系统是否有精美的显卡”),而 FOO 使用 Lib1为了做这件事,它可以使构建系统(makefile 或类似文件)更简单地始终链接到 lib1,即使在未设置 USE_FOO 时您实际上并不需要它。

但总的来说,不要链接到不需要的库。它会导致更多的依赖关系,这绝不是一件好事。

于 2012-12-21T10:18:44.870 回答