关于Linux c ++静态库

时间:2014-03-13 10:37:49

标签: c++ linux

这里我有几个问题,静态库需要你的帮助。

从一些书中我了解到,静态库(Linux中的.a)包含一组编译对象,当它链接到可执行文件时,链接工具将只取出那些实际引用的对象。

因此,如果.a包含1.o,2.o和3.o并且我的应用程序仅使用1.o中的函数,那么只有1.o将内置到可执行文件中,这是正确的吗?

然后让我们走得更远,说我们有2个.l libs,首先包含1.o,2.o和3.o,第二个包含3.o 4.o和5.o.如果我的应用程序只使用1.o 2.o 3.o和4.o中的函数,那么只有这些4 .o将被内置到可执行文件中,它是否正确?

我提出了这个问题,因为我正在构建一些与MSVC一起使用的.a文件。这些.a库是在MinGW中构建的,然后应该与MSVC兼容。我可以将这些库包含到MSVC项目中并成功构建我的程序。但是生成的可执行文件是5 MB(所有.a的总大小应该是大约8MB),即使我的程序是空的(只有一个空主函数)。

这是否意味着,.a在MSVC中使用或.lib(Win的静态库)将作为一个整体构建到可执行文件中,但不是在Linux下的行为方式?

我也有一个关于以下内容的问题

enter image description here

如果我可以使用-static链接到lib tiff的静态版本,那么为什么需要链接到其他库?静态库是否应该包含它需要的所有代码?

由于

1 个答案:

答案 0 :(得分:1)

静态库不会包含所需的所有代码。想象一下使用printf()输出错误消息的库。这个库仍然依赖于libc的静态版本,它不包含printf本身的代码。

在你的情况下,由于Tiff支持各种内部表示格式,其中一种是jpeg,静态libtiff希望你链接静态libjpeg。

Windows和Linux之间没有根本区别。当您对libtiff和libjpeg进行静态链接时,只有libtiff实际需要的libjpeg函数会被链接,但不会,例如,处理JFIF Jpeg包装器的部分。

编辑 - 回复评论

main()被调用之前,有很多事情要发生。在linux / unix上并没有那么多,操作系统以main()想要的方式提供参数,但在Windows上,一个不同的函数,通常称为WinMain(),在程序启动时获得控制权。此WinMain()隐藏在库中。它在一个字符串中获取整个命令行,并且必须解析参数以将它们传递给main(),这意味着检查空格,这可能是使用isspace()来实现的,它引入了ctype,这会拉入很多依赖于语言环境的东西,等等。你的5 MB中的大部分都可能是用于使程序在windows中工作的代码,就像在unix中一样。此外,如果您正在使用调试选项进行编译,则这些调试符号也会占用大量空间。

Keltar关于静态库调用动态库的评论也是正确的 - 但这增加了一个你不经常需要的复杂功能。静态链接有两个或多或少的原因:

  • 您希望您的程序即使在动态库出现问题时也能运行。如果我意外rm /lib/libc.so.*如果我有mountcp的静态链接版本,我会很高兴从其他地方复制它。因此,安装程序和“紧急程序”通常是静态链接
  • 您希望确保您的程序使用特定版本的库,这些库在编译时是系统上最新的,而不是5年后可能在某个系统上安装的dynalink版本。

如果某些所有库都是静态的,这两个原因都没有多大意义。

但有例外:想象一下你需要libtiff中的特定功能。您浏览文档,它没有说明该功能。您检查源代码并发现它实现了specific_feature(),其中包含一个很大的“这是实验性的,可能会在将来的版本中消失”评论。如果您确定需要该功能 now ,则可能需要静态链接libtiff以防止未来版本的libtiff不再实现该功能时使您的程序失败。当然,您仍然需要动态版本的libjpeg和libc。如果这对你来说是好的做法,我会留下决定。

Windows是一种特殊情况,因为它总是使用kernel.dll和user32.dll,因为 没有静态版本,即使你的程序的其余部分是静态链接的。

因此,虽然libtiff.a 可能需要libjpeg.so,并且libtiff.lib 可能需要libjpeg.dll,但通常没有太多理由这样做。