如果与未使用的库链接,可执行文件的构建方式是否不同?
Is an executable built differently if linked against a library that's not used?
除了较长的编译时间外,是否有链接到未使用的库中的缺点?
例如,在编译以下方式之一的程序的可执行文件中是否有任何差异:
g++ -o main main.cpp
g++ -o main main.cpp -llib1 -llib2 -llib3 -lmore
*实际上没有库文件来构建主。
我认为这没有区别,因为文件大小是相同的,但是我要求确认。
它取决于。
-
如果
liblib1.a
,liblib2.a
和liblib3.a
是静态库,并且没有从中使用符号,则不会有区别。 -
如果共享库是
liblib1.so
,liblib2.so
或liblib3.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]
注释
-
必须在库之前指定
--as-needed
标志。它仅影响出现在其之后的库。因此gcc -lpng -Wl,--as-needed
不起作用。 -
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。
但总的来说,不要链接到不需要的图书馆。它会导致更多的依赖性,这绝不是一件好事。
- 不同/较旧的处理器运行c++代码的方式是否不同
- 并发/多线程:是否可以以这种方式生成相同的输出?
- 这种方式是否可以接受向向量添加unique_ptr?
- 在线程中读取无符号整数时,c++ 位是否以原子方式切换?
- 在 Eclipse 中添加库的工作方式是否与在 Visual Studio 中相同?
- VS2017 是否更改了 C++ 中访问 C# 命名空间的方式?
- 是否可以使用非常量指针调用非常量函数,以及当两个unique_ptrs指向同一个对象时程序的行为方式?
- 我是否可以使用 win32 句柄以编程方式记录发送到/接收到 USB/COM 的内容
- 我们是否应该转向新的自我分配保护方式?
- 以这种方式初始化的 char 数组是否会自动添加空终止符?
- clang++ 是否以更轻松的方式处理系统标头?
- size_t的大小和对齐方式是否与ptrdiff_t相同?
- 是否可以以编程方式构造 std::initializer_list?
- 是否有任何优雅的方式来遍历元素位置可以更改的列表?
- 只需要知道我在c ++中打印模式的方式是否有效,或者有另一种方法可以有效地做到这一点
- 是否可以在C++中以间接方式包含头文件
- C++:这两种将数字写入矩阵的方式之间是否存在显着的速度差异?
- 我的随机生成器是否不工作,或者我决定人/骨架是否击中对手的方式是否有错误
- 我是否以错误的方式声明了getpriorityvalues函数
- 是否有用于"go to variable type definition" C++中"auto"变量的 Visual Studio 键盘快捷方式?