【问题标题】:Why does the C++ linker require the library files during a build, even though I am dynamically linking?为什么 C++ 链接器在构建期间需要库文件,即使我是动态链接的?
【发布时间】:2011-01-03 00:54:47
【问题描述】:

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

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

【问题讨论】:

  • 链接器需要知道哪个 DLL 包含它需要解析的导出。 .lib 文件提供此信息。
  • 您询问的是 .dll 还是 .so? linux 的答案会有所不同。

标签: c++ gcc linker visual-c++


【解决方案1】:

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

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

【讨论】:

  • 所以如果我理解正确的话:作为“隐式”动态链接的替代方法(在构建期间链接到 .lib,在运行时使用 DLL) - 我可以在运行时使用“显式”链接(在 Windows 上)LoadLibrary() 加载 DLL,GetProcAddress() 返回指向我正在调用的方法的函数指针。需要编写更多代码,但在构建时我不需要 .lib。
【解决方案2】:

Raymond Chen 写了几篇专门针对 Windows 的博客文章。以The classical model for linking 开头,然后以Why do we have import libraries anyway? 跟进。

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

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

【讨论】:

    【解决方案3】:

    一方面,链接器会插入链接时存在的库版本,以便在更新库版本时您的程序有一些机会工作。一个系统上可以存在多个版本的共享库。

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-03-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-10-22
            • 2011-01-01
            相关资源
            最近更新 更多