【问题标题】:C/C++. Advantages of libraries over combined object filesC/C++。库相对于组合目标文件的优势
【发布时间】:2011-09-08 17:49:37
【问题描述】:

虽然在一个库中组合多个目标文件是很常见的,但可以(至少在 Linux 中)将多个目标文件组合成另一个目标文件。

(见combine two GCC compiled .o object files into a third .o file

因为使用库而不是仅仅组合目标文件也有缺点:

1:链接时只使用一种类型的文件(对象)会更容易,特别是如果所有文件都做同样的事情。

2:链接时(至少在GCC中),库(默认)需要排序,不能处理循环依赖。

我想知道图书馆有什么优势(除了第 22 条,它们被大量使用)。

搜索了一段时间后,我得到的唯一解释似乎是单个库比多个目标文件更好。

【问题讨论】:

  • 首先您需要澄清“库”的含义。您是指共享对象(foo.so),还是在谈论档案(foo.a)? gcc 和 gnu ld 可以很好地处理 .a 文件的循环依赖关系,您只需多次指定每个 .a 文件。
  • @George "gnu ld 可以很好地处理 .a 文件的循环依赖关系,您只需多次指定每个 .a 文件" - 这是“很好”的有趣定义。
  • @Neil Butterworth 好吧,当多次指定每个库文件时,最好将所有符号视为多重定义。如果我没记错的话,这是处理 .a 文件之间循环依赖关系的“推荐”方法。
  • 在 GCC 中,使用 -Wl,-( -Wl,-) 使链接器重复循环通过 直到所有可以解析的所需符号都被解析。 (IIRC)

标签: c++ c linker object-files


【解决方案1】:

虽然它取决于所使用的链接器,但目标文件完整地包含在最终二进制文件中。因此,如果您将多个目标文件组合成一个目标文件,则生成的(组合的)目标文件将包含在生成的二进制文件中。

相比之下,库只是一个目标文件库。链接器只会从库中提取解析所有符号链接所需的目标文件。如果不需要目标文件(在库中),则它不包含在二进制文件中。

【讨论】:

    【解决方案2】:

    通常库更好,因为链接器可以优化库中未使用的 .o 文件。

    以某种方式组合文件也有一些优势:

    • 如果您将所有源文件合并到一个文件中,那么编译速度会大大提高。
    • 有时在 C++ 中,链接器可能会优化掉您不想优化的 .o 文件。例如,当您需要在此处定义但未在任何其他翻译单元中使用的对象的构造函数的副作用时。

    【讨论】:

    • “将所有源文件合并到一个 [...] 极大地提高了编译速度。”真的吗?当您无论如何都必须重新编译所有内容时,这可能是真的。当您在包含数千个源文件的项目中对单个源文件进行迭代更改时?不太可能。
    • @andrewski:这是在编译库的上下文中说的,而不是在数千个源文件的整个项目中。当您设计库时,使用单独的文件确实更容易。如果库中的类彼此紧密耦合,则链接器无法优化单个 .o 输出。合并源文件并不难,将它们放在一个文件中会大大加快库用户的编译速度。
    • whefs library proves by example 认为编译合并(合并的源文件)比编译单个源文件要快得多。
    【解决方案3】:

    如果您使用目标文件,那么目标文件中的所有代码都会放在您的应用程序中。如果你使用库,那么只有需要的代码是。

    【讨论】:

    • 好的,谢谢。那么一个更好的问题可能是为什么不总是使用库文件,而只是 -ar 每个对象,因为它是制作的(除了包含专门用于运行时链接的未引用元素的对象)。
    • @Simon 您想将 .o 文件用于作为特定项目一部分的组件(因为如果不使用它们,您为什么首先编写它们)和 .a 文件用于事物这可能是项目的一部分。例如,我自己的实用程序库包含一些 ODBC 代码,但我编写的应用程序很少使用它,我不希望它与那些不使用它的应用程序链接。
    • 这很正常,当然。但为什么?如果只能使用 .a,为什么还要使用 .o 和 .a。即使您的项目中不太可能有许多未引用的符号。 (GCC 源有一些遗留的)。
    • @Simon 抱歉,我想我的解释不能更清楚。
    • 您的解释给出了使用 .a 的理由和使用 .o 的规则。它没有给出规则的理由。基本上,将您的 ODBC 作为 .a 并将您的项目也作为 .a 会有什么问题(除了它是一种约定)(优点是您只需要使用一种类型的文件)。 - 不想争论,只是想弄清楚这一点。
    【解决方案4】:

    一个原因是 .a 库中的对象只会被拉入以满足 undefined 符号引用 - 因此,如果您希望允许调用应用程序定义符号的可能性,或者在“库”代码中使用默认定义,可以使用真正的库来执行此操作,但不能使用单个 .o 文件。

    【讨论】:

      猜你喜欢
      • 2014-05-18
      • 1970-01-01
      • 2016-02-28
      • 2018-10-22
      • 2014-09-26
      • 1970-01-01
      • 1970-01-01
      • 2011-08-14
      • 1970-01-01
      相关资源
      最近更新 更多