【问题标题】:Can code for a library function be contained several times in an executable?库函数的代码可以多次包含在可执行文件中吗?
【发布时间】:2014-06-24 13:12:29
【问题描述】:

我想知道,在用 C 编写的程序中,静态库中的函数代码是否会在可执行文件中包含两次。

例如,假设您创建了一个静态库 lib_a,它使用来自另一个静态库 lib_b 的函数。然后创建一个同时使用 lib_a 和 lib_b 的程序。该程序的可执行文件是否会包含两次来自 lib_b 的函数的代码?如果没有,如何避免?

我对链接器和可执行文件格式的理解非常粗略;对不起,如果这个问题很基本。也许有人知道这个主题的好参考?我已经搜索了几本关于 C 的书籍,但我找不到答案。

【问题讨论】:

  • 它会被包含两次,如果你不想要它,你应该创建一个lib_c,将lib_b和lib_a合并,并用lib_c替换源文件lib_b和lib_a。更多解释herehere
  • @Yann 你确定吗?使用全局变量,不能将多个定义链接在一起。使用全局函数可以吗?
  • 我仍在等待专家级程序员,但同时让我检查一下我的理解。创建使用来自 lib_a 的函数的静态库 lib_b 并不意味着将来自 lib_a 的代码包含在 lib_b 中。 lib_b 将对 lib_a 中的函数具有“未解析的引用”(创建 lib_b 时甚至不必存在 lib_a)。事实上,在典型的 unix 环境中,生成一个解决了所有依赖关系的库至少是不寻常且困难的,因为该步骤通常在链接可执行文件时完成。

标签: c linker executable


【解决方案1】:

您还可以在 @Yann 建议的基础上将 lib_b 转换为共享库

【讨论】:

    【解决方案2】:

    假设库lib_a.a(一个Unix 风格的静态库)包含一个函数a1_function(),而a1_function() 调用另一个函数b1_function(),该函数位于lib_b.a

    假设你的程序直接调用a1_function(),并且还直接从lib_b.a调用另一个函数b2_function()

    您的链接器命令可能如下所示:

    c99 -o program program.c -l_a -l_b
    

    如果不同时提及lib_a.a(如-l_a 或通过路径名)和lib_b.a,您将无法链接您的程序。即使您稍后修改您的程序使其不再调用b2_function(),您仍然需要这两个库,因为lib_a.a 只包含它自己的代码,而不是lib_b.a 中的代码。

    使用共享库,可以将修改后的程序(不直接调用b2_function())与-l_a 链接,并依靠lib_a.so 中的元数据告诉链接器与@987654339 链接@也是。

    如果您修改lib_a.a,使其不仅包含a1_function(),还包含b1_function() 的代码以及支持它所需的任何支持代码(出于本讨论的目的,将排除b2_function())。那么只调用a1_function() 的程序就根本不需要lib_b.a。但是,如果程序调用b2_function(),那么您将需要链接这两个库。来自lib_a.a 的满足b1_function() 的材料及其依赖项将来自lib_a.a;函数b2_function() 和它需要的任何不是lib_a.a 提供的支持材料也将被链接。

    如果lib_a.a 中包含的来自lib_b 的代码与lib_b.a 中的“相同”代码不同,则您可能会出现异常行为。一个极端的例子可能是一个目标文件b_file1.c,它包含许多函数,包括b1_function()b2_function()。当编译包含在lib_a.a 中时,b2_function() 不包括在内;当编译包含在lib_b.a 中时,b2_function() 包括在内(并且始终包括b1_function())。那么当程序调用b2_function() 时,您将无法链接程序,因为程序将从lib_a.a 链接b_file1.o 以满足b1_function() 引用,但链接器也会尝试将b_file1.olib_b.a 链接到满足b2_function() 参考。这导致函数b1_function() 的两个定义,这是不允许的(在静态库链接规则下)。对于共享库,并不完全清楚会发生什么,但有多种方式可能会出错(但双重定义符号的错误不会是其中一种方式)。

    请注意,您应该谨慎避免lib_a.a 中的函数调用lib_b.a 中的函数而lib_b.a 中的函数调用lib_a.a 中的函数的情况。这会导致循环依赖问题,并且可能意味着您需要在命令行上多次列出库。最好创建一个单独的库,lib_c.a,其中包含来自lib_a.alib_b.a 的材料并与它链接一次。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多