繁体   English   中英

为什么 C++ 链接器在构建过程中需要库文件,即使我是动态链接的?

[英]Why does the C++ linker require the library files during a build, even though I am dynamically linking?

我有一个 C++ 可执行文件,并且我正在动态链接多个库(Boost、Xerces-c 和自定义库)。

我明白为什么我需要 .lib/.a 文件,如果我选择静态链接这些库( 相关的 SO 问题在这里)。 但是,如果我动态链接到这些外部库,为什么在链接我的可执行文件时需要提供相应的 .lib/.so 库文件?

编译器不知道动态链接,它只知道函数通过其原型存在。 链接器需要 lib 文件来解析符号。 DLL 的 lib 包含附加信息,例如函数所在的 DLL 以及它们如何导出(按名称、按序数等)。 DLL 的 lib 文件比包含完整目标代码的 lib 文件包含的信息少得多 - libcmmt我系统上的 .lib 是 19.2 MB,但 msvcrt.lib 是“仅”2.6 MB。

请注意,此编译/链接模型此时已有近 40 年的历史,并且早于大多数平台上的动态链接。 如果它是今天设计的,动态链接将是一等公民(例如,在 .NET 中,每个程序集都有丰富的元数据来准确描述它导出的内容,因此您不需要单独的头文件和库。)

Raymond Chen 写了几篇关于此特定于 Windows 的博客条目。 链接的经典模型开始,然后跟进为什么我们仍然有导入库? .

总而言之,历史将编译器定义为知道详细类型信息的组件,而链接器只知道符号名称。 所以链接器最终创建了没有类型信息的 .DLL,因此想要链接它的程序需要某种元数据来告诉它函数是如何导出的,以及它们采用和返回的参数类型。

.DLL 没有您需要直接链接到它们的所有信息的原因是历史性的,而不是技术限制。

一方面,链接器会插入链接时存在的库版本,这样如果库版本更新,您的程序就有机会运行。 一个系统上可以存在多个版本的共享库。

链接器的任务是验证所有未定义的符号是否都被考虑在内,无论是静态内容还是动态内容。

默认情况下,它坚持所有符号都存在。

但是,这只是默认设置。 请参阅 -z 和 --allow-shlib-undefined 以及朋友。

也许这个动态链接是通过导入库完成的(函数在定义之前有 __declspec(dllimport))。
如果这是编译器预期的方式,则声明了 __imp_symbol 函数,该函数负责将调用转发到动态加载的正确库。
这些函数是在符号与 __declspec(dllimport) 关键字链接期间生成的

这是一个非常简单的描述,可能会有所帮助。 静态链接将运行程序所需的所有代码放入可执行文件中,以便找到所有内容。 动态链接意味着某些必需的代码不会放入可执行文件中,而是会在运行时找到。 我在哪里可以找到它? 有函数 x() 吗? 如何调用函数 x()? 这就是库在动态链接时告诉链接器的内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM