为什么 gcc 中的弱属性在静态库中的工作方式与目标文件不同?
Why does weak attribute in gcc work differently in static library than for object files?
关于堆栈溢出,有许多线程将弱符号链接到静态库混淆。简而言之,当只使用目标文件(不使用库)时,weak 总是会被一个 strong 对应的符号覆盖。但是当使用静态库时,事情会变得混乱。我不会在这里解释差异,但是堆栈溢出上有线程解释它们。我的问题是他们为什么这样做?目前这对我来说毫无意义。
编辑
相关堆栈溢出线程的链接:
- 2
- 3
- 4
混淆的解释:
weak 的目的是(在我看来)因此用户可以在需要时用自己的函数覆盖函数(或用于语言内部使用,例如 inline
),但是当库创建者覆盖相同(或底层)存档内的函数,它没有被覆盖,链接器只需选择它看到的第一个定义。这与“扁平”(无库)结构不一致。
The purpose of weak is (in my mind) so the user can overwrite a function with their own when it is needed (or for the language internal usage, e.g., for inline),
是也不是。我会缩小范围并改变重点:弱符号的目的是让 库 可以提供库的其他函数使用的某些函数的默认实现,但也允许程序使用该库替换他们自己的实现。
此外,虽然这并不排除静态库的使用,但它主要用于动态库,因为当您 linking 静态库时,您不需要为此目的使用弱符号。另一方面,共享库需要以不同的方式构建,并得到动态 linker 的支持以允许此类替换。
but when a library creator overwrites a function inside of the same (or underlying) archive it is not overwritten, the linker simply chooses the first definition it sees.
然后呢?静态库的创建者可以控制其内容,包括它们的顺序。如果他们打算提供给定符号的特定强定义,那么将该符号的任何其他外部定义放入同一个库中至少是一种浪费。
是的,静态 linker 仍然可以在那个分数上覆盖库作者,但这种情况不是弱符号旨在支持的情况,所以 linker 维护者为什么要这样做期望花费大量的工作来实现它,并承诺无限期地维护它?
Which is not consistent with the "flat" (libraryless) structure.
这取决于您如何在“扁平”情况下执行 link。此外,link将(仅)目标文件的集合组合成一个完整的程序仍然不是弱符号设计支持的场景。
why did they make it that way?
如果你想要一个权威的答案,你将不得不问设计师,但我的看法是 GCC 工具链的作者和维护者认为你所询问的静态 link 行为是一个合理的妥协在工具的复杂性和弱符号的理想语义之间。他们可能在这一领域受到了 SUN 工具的影响,而 SUN 工具实际上可能是实际做出决定的地方。
所选择的细节很好地满足了弱符号的预期目的,而且我相当有信心,包含同一符号的弱定义和强定义的库不在指导工具设计的用例中。 linking 对象文件的行为直接不同于从静态库中 linking 对象文件的行为可以被认为是不一致的,但这是您对过程的心理模型的问题。无论如何,我倾向于认为当时提出的问题是“用户最可能的意思是什么?”,并且对于 linking 多个目标文件(大概全部由程序/库作者提供)至于 linking 静态库(通常由第三方提供)。
关于堆栈溢出,有许多线程将弱符号链接到静态库混淆。简而言之,当只使用目标文件(不使用库)时,weak 总是会被一个 strong 对应的符号覆盖。但是当使用静态库时,事情会变得混乱。我不会在这里解释差异,但是堆栈溢出上有线程解释它们。我的问题是他们为什么这样做?目前这对我来说毫无意义。
编辑
相关堆栈溢出线程的链接:
- 2
- 3
- 4
混淆的解释:
weak 的目的是(在我看来)因此用户可以在需要时用自己的函数覆盖函数(或用于语言内部使用,例如 inline
),但是当库创建者覆盖相同(或底层)存档内的函数,它没有被覆盖,链接器只需选择它看到的第一个定义。这与“扁平”(无库)结构不一致。
The purpose of weak is (in my mind) so the user can overwrite a function with their own when it is needed (or for the language internal usage, e.g., for inline),
是也不是。我会缩小范围并改变重点:弱符号的目的是让 库 可以提供库的其他函数使用的某些函数的默认实现,但也允许程序使用该库替换他们自己的实现。
此外,虽然这并不排除静态库的使用,但它主要用于动态库,因为当您 linking 静态库时,您不需要为此目的使用弱符号。另一方面,共享库需要以不同的方式构建,并得到动态 linker 的支持以允许此类替换。
but when a library creator overwrites a function inside of the same (or underlying) archive it is not overwritten, the linker simply chooses the first definition it sees.
然后呢?静态库的创建者可以控制其内容,包括它们的顺序。如果他们打算提供给定符号的特定强定义,那么将该符号的任何其他外部定义放入同一个库中至少是一种浪费。
是的,静态 linker 仍然可以在那个分数上覆盖库作者,但这种情况不是弱符号旨在支持的情况,所以 linker 维护者为什么要这样做期望花费大量的工作来实现它,并承诺无限期地维护它?
Which is not consistent with the "flat" (libraryless) structure.
这取决于您如何在“扁平”情况下执行 link。此外,link将(仅)目标文件的集合组合成一个完整的程序仍然不是弱符号设计支持的场景。
why did they make it that way?
如果你想要一个权威的答案,你将不得不问设计师,但我的看法是 GCC 工具链的作者和维护者认为你所询问的静态 link 行为是一个合理的妥协在工具的复杂性和弱符号的理想语义之间。他们可能在这一领域受到了 SUN 工具的影响,而 SUN 工具实际上可能是实际做出决定的地方。
所选择的细节很好地满足了弱符号的预期目的,而且我相当有信心,包含同一符号的弱定义和强定义的库不在指导工具设计的用例中。 linking 对象文件的行为直接不同于从静态库中 linking 对象文件的行为可以被认为是不一致的,但这是您对过程的心理模型的问题。无论如何,我倾向于认为当时提出的问题是“用户最可能的意思是什么?”,并且对于 linking 多个目标文件(大概全部由程序/库作者提供)至于 linking 静态库(通常由第三方提供)。