返回

微软 C 库重复符号疑云:理解 PE 库机制,化解链接难题

windows

微软 C 库中的重复符号:揭开谜团,找到答案

引言

在为 Windows PE 格式目标文件进行链接时,你是否曾遇到一个恼人的问题,即尝试使用 libcmt.lib 链接微软编译器生成的目標文件时,出现大量重复符号?如果你有,那么你并不孤单。在这篇文章中,我们将深入探讨这个问题的原因,并提供切实可行的解决方案,助你成功完成链接任务。

重复符号的成因

让我们以 cosl 符号为例。它在 libcmt.lib 中由三个不同的对象定义,它们引用不同的地址,指向名称为 .text$mn 的文本段,并且存储类为 IMAGE_SYM_CLASS_EXTERNAL。这些重复的定义似乎都是真实的,但为什么会出现呢?

备选版本还是语义误解?

这些重复的定义是否为备选版本,由链接器根据特定标准从中选择?还是我们对 PE 库格式的语义存在误解?

深入剖析 PE 库格式

为了厘清这个问题,我们必须深入了解 PE 库格式。PE(可移植可执行文件)库是一个二进制文件,其中包含可链接的模块,例如函数、数据和资源。每个模块由一个符号表,其中列出了模块中定义的符号。

符号作用域和重定义

在 PE 库中,符号具有作用域,这意味着它们仅在定义它们的模块内可见。然而,符号可以被其他模块重定义,这意味着其他模块可以提供具有相同名称但不同定义的符号。

微软 C 库中的重复符号

回到 libcmt.lib 中的重复符号,这些符号并不是备选版本。相反,它们是由不同的模块定义的,这些模块代表微软 C 运行时库的不同组件。例如,cosl 符号可能由处理三角函数的模块和处理复数的模块分别定义。

解决重复符号问题

为了解决重复符号问题,链接器必须选择一个符号的定义。它通常会选择第一个遇到的定义,但也可以通过指定符号的顺序或使用链接器选项来覆盖此默认行为。

处理 libcmt.lib

对于 libcmt.lib,微软建议使用 /FORCE 选项,该选项强制链接器将库中定义的符号作为外部符号,从而忽略任何重定义。通过这种方式,链接器将选择 libcmt.lib 中定义的符号,而忽略目标文件中任何重复的定义。

结论

微软 C 库中重复符号的出现是由 PE 库格式中的符号作用域和重定义机制造成的。通过理解这些概念并使用适当的链接器选项,你可以成功链接包含 libcmt.lib 的目标文件,从而避免重复符号错误。

常见问题解答

  1. 为什么 libcmt.lib 中会出现重复符号?

    • 符号被不同的模块定义,这些模块代表微软 C 运行时库的不同组件。
  2. 如何解决重复符号问题?

    • 使用 /FORCE 链接器选项强制链接器将库中定义的符号作为外部符号。
  3. 哪些符号会导致重复?

    • 在 libcmt.lib 中,cosl 等符号可能会被多个模块定义。
  4. 重复符号有什么影响?

    • 重复符号可能会导致链接器错误或应用程序不稳定。
  5. 是否可以在不使用 /FORCE 选项的情况下解决重复符号问题?

    • 是的,可以通过指定符号的顺序或使用其他链接器选项。