微软 C 库重复符号疑云:理解 PE 库机制,化解链接难题
2024-03-22 17:34:23
微软 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 的目标文件,从而避免重复符号错误。
常见问题解答
-
为什么 libcmt.lib 中会出现重复符号?
- 符号被不同的模块定义,这些模块代表微软 C 运行时库的不同组件。
-
如何解决重复符号问题?
- 使用
/FORCE
链接器选项强制链接器将库中定义的符号作为外部符号。
- 使用
-
哪些符号会导致重复?
- 在 libcmt.lib 中,
cosl
等符号可能会被多个模块定义。
- 在 libcmt.lib 中,
-
重复符号有什么影响?
- 重复符号可能会导致链接器错误或应用程序不稳定。
-
是否可以在不使用
/FORCE
选项的情况下解决重复符号问题?- 是的,可以通过指定符号的顺序或使用其他链接器选项。