如果与未使用的库链接,可执行文件的构建方式是否不同?

Is an executable built differently if linked against a library that's not used?

本文关键字:是否 方式 构建 未使用 链接 如果 可执行文件      更新时间:2023-10-16

除了较长的编译时间外,是否有链接到未使用的库中的缺点?

例如,在编译以下方式之一的程序的可执行文件中是否有任何差异:

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

*实际上没有库文件来构建主。

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

它取决于。

  1. 如果 liblib1.aliblib2.aliblib3.a是静态库,并且没有从中使用符号,则不会有区别。

  2. 如果共享库是liblib1.soliblib2.soliblib3.so,则无论是否使用它们,它们都会在运行时加载它们。您可以使用Linker Flag --as-needed更改此行为,并建议使用此标志。

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

$ CAT MAIN.Cint main(){    返回0;}$ gcc main.c$ readelf -d a.out |格雷普需要 0x0000000000000001(需要)共享库:[libc.so.6]$ gcc -lpng main.c$ readelf -d a.out |格雷普需要 0x0000000000000001(需要)共享库:[libpng12.so.0] 0x0000000000000001(需要)共享库:[libc.so.6]

您可以在我的系统上看到-lpng链接到libpng12.so.0,无论是否实际使用了符号。--as-needed链接器标志修复了以下操作:

$ gcc -wl, - 需要-lpng main.c$ readelf -d a.out |格雷普需要 0x0000000000000001(需要)共享库:[libc.so.6]

注释

  1. 必须在库之前指定--as-needed标志。它仅影响出现在其之后的库。因此gcc -lpng -Wl,--as-needed不起作用。

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

取决于您是链接静态库还是共享库。如果要链接静态库,则每个添加的可执行文件大小将增加。链接到共享库,不会大大增加可执行文件的大小,只添加了库符号。

绝对是。不利的一面是,由于某种原因,其他人(或将来您将来)将假设库> 。大多数人不会花时间削减程序的依赖性,因此它们的列表成长和增长。

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

上面有一些非常好的答案。另一个注释是"它真正有什么区别"。已经提到的是维护成本(例如,当某人安装新的操作系统(没有LIB3)时,用户必须去某处找到lib3并安装它,并且因为lib3也需要lib17已安装,它为用户添加了更多工作)。

但是,当您加载二进制文件时,如果您已经针对未使用的共享库链接,则系统仍会查找这些库,如果不存在,则拒绝加载 - 这会增加时间并安装噩梦。

加载代码后,它不应有其他运行时罚款。

话虽如此,有时会有争论与未使用的图书馆有关。假设您的代码有一个选项use_foo,其中仅根据构建时的某个任意选择包含foo功能(例如,在linux内核上这是在linux内核上> 3.0> 3.0"或"系统是否具有精美的图形卡"),而foo for foo usisa则使用lib1要进行业务,它可以使构建系统(MakeFile或类似)变得更简单,即使您在未设置USE_FOO时实际上不需要链接,也可以始终链接到LIB1。

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

相关文章: