除了更长的编译时间,链接未使用的库是否有任何缺点?
例如,在以下两种方式之一编译的程序的可执行文件中是否存在任何差异:g++ -o main main.cpp
g++ -o main main.cpp -llib1 -llib2 -llib3 -lmore
*实际上不需要库文件来构建main。
我认为没有区别,因为文件大小相同,但我要求确认。
答案 0 :(得分:14)
取决于。
如果liblib1.a
,liblib2.a
和liblib3.a
是静态库,并且没有使用任何符号,那么就没有区别了。
如果liblib1.so
,liblib2.so
或liblib3.so
是共享库,则无论是否使用它们,它们都将在运行时加载。您可以使用链接器标志--as-needed
来更改此行为,建议使用此标志。
要检查二进制文件在运行时直接加载哪些共享库,可以在ELF系统上使用readelf
。
$ cat main.c int main() { return 0; } $ gcc main.c $ readelf -d a.out | grep NEEDED 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] $ gcc -lpng main.c $ readelf -d a.out | grep NEEDED 0x0000000000000001 (NEEDED) Shared library: [libpng12.so.0] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
您可以在我的系统上看到-lpng
与libpng12.so.0
的链接,无论是否实际使用了它的符号。 --as-needed
链接器标志修复了这个问题:
$ gcc -Wl,--as-needed -lpng main.c $ readelf -d a.out | grep NEEDED 0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
{<1}}标志必须在之前指定库。它只会影响它后面出现的库。因此--as-needed
不起作用。
gcc -lpng -Wl,--as-needed
命令不仅列出了二进制文件直接链接的库,还列出了所有间接依赖项。这可能会根据这些库的编译方式而改变。只有ldd
会向您显示您的直接依赖关系,并且只有readelf
会向您显示间接依赖关系。
答案 1 :(得分:0)
这取决于您是链接静态库还是共享库。如果要链接静态库,则每次添加时可执行文件的大小都会增加。链接到共享库,不会大大增加可执行文件的大小,只会添加库符号。
答案 2 :(得分:0)
绝对是的。缺点是其他人(或者您将来)会假设由于某种原因需要 库。大多数人不会花时间削减程序的依赖关系,因此它们的列表会增长和增长。
成本与已编译的代码无关,而是与维护和移植程序有关。
答案 3 :(得分:0)
上面有一些非常好的答案。另一个注意事项是“它真正有什么不同”。已经提到的是维护成本(例如当有人安装一个没有Lib3的新操作系统时出现问题,因此用户必须去某个地方找到lib3并安装它,并且因为lib3也需要lib17而你也不是安装后,它为用户增加了更多的工作)。
但是,当你加载二进制文件时,如果你链接到实际没有使用的共享库,系统仍然会查找那些库,如果它们不存在则拒绝加载 - 这会增加时间,并安装噩梦。
加载代码后,它应该没有额外的运行时惩罚。
话虽如此,有时也会有与未使用的库链接的论据。假设您的代码有一个选项USE_FOO,其中FOO功能仅包含在构建时基于某些任意选择(例如“这是在Linux内核&gt; 3.0上”或“系统是否具有花哨的图形卡”),并且FOO使用Lib1做它的业务,它可以使构建系统(makefile或类似)更容易总是链接lib1,即使你没有设置USE_FOO时实际上不需要它。
但总的来说,不要链接不需要的库。它会导致更多的依赖关系,这绝不是一件好事。