【问题标题】:Why do dynamically linked imports (in Windows) always load at application start up time?为什么动态链接导入(在 Windows 中)总是在应用程序启动时加载?
【发布时间】:2019-05-05 23:58:56
【问题描述】:

动态链接到库的一个好处是,当调用该库中的函数时,会将其加载到程序的虚拟地址空间中,然后调用该函数。静态链接会加载整个可执行文件,占用空间。

在 Windows 上,当加载程序时,甚至在调用程序入口点之前,所有函数导入都已解析。例如:kernel32.dll!VirtualFree。加载所有需要的库,然后调用程序的入口点。

这与静态链接的可执行文件有何不同?如果一次加载所有引用的库,它会不会占用相同数量的空间?有什么好处?请帮我理解。

【问题讨论】:

    标签: windows dll load static-libraries


    【解决方案1】:

    事实上,对于所有运行 Windows 的 DLL,不是 应用程序取决于在启动时加载。自 Visual C++ 6.0 (1998) 以来, MS linker has supported the /DELAYLOAD option 延迟 DLL 的加载,直到调用其导出之一。

    默认行为是在启动时加载 DLL。我假设你想知道 在以下方面,默认行为如何与链接静态库进行权衡 内存占用等。

    假设具有相同实现的相同 API 构建为静态 库libfoo.lib 和动态库libfoo.dll

    只要在给定时间只有一个程序需要libfoo.dll,那么至少 当时消耗的内存与同一程序消耗的内存一样多,如果 它与libfoo.lib 静态链接。

    其实加载DLL的程序版本很有可能会消耗更多内存 而不是与静态库链接的那个。这是因为当为 第一次,整个 DLL 被加载到内存中。但事实上,不是的情况是,当一个程序链接到一个静态库时,整个静态库必须合并到可执行文件中。 static library 只是目标文件的存档,链接器从中 默认情况下仅提取定义程序引用的符号的符号, 并将他们链接到程序中,忽略其余部分。因此,如果程序不需要libfoo.lib 中存档的所有目标文件, 那么静态链接libfoo.lib所需的内存将更小 比动态链接libfoo.dll所需的内存。

    但是,一旦更多,内存成本就会开始有利于 DLL 一个正在运行的程序同时需要libfoo.dll。那是 因为 DLL 由加载器可以单独加载的不同代码和数据部分组成。 每个需要libfoo.dll 的并发程序都需要有自己的 DLL 的 data,但它们都可以执行其 code 的相同副本。后 libfoo.dll - 代码和数据部分 - 已为第一个加载 需要它的程序,加载器只需加载其数据的新副本 对于任何需要它的并发程序。

    所以当我们考虑整个运行系统的内存占用时,其中 许多并发进程可能需要单个库提供的服务, 在 DLL 而不是静态库中实现此类服务是经济的 战略。

    DLL 的主要目的是以只有一个副本的方式提供服务 无论有多少并发程序,都必须加载实现代码 正在执行它。

    但它们还有另一个重要的好处,即使对于那些 只可能被一个应用程序使用。当 foo 库的新版本发布时 制作,提供错误修正或增强,这是可以部署此版本的唯一方法 与静态库libfoo.lib 链接的程序是 重新链接、重新分发和重新安装所有这些程序。但只要新 libfoo 的发布保留了现有的 API,什么都不需要做 与已与libfoo.dll 链接的程序。只需要 分发和安装libfoo.dll 的新版本,这些程序将 下次运行时加载它。应用程序架构师可以选择 精确地在 DLL 中实现应用程序特定功能的模块 可以部署此功能的更新,而无需最终用户 重新安装应用程序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-28
      • 2023-04-05
      • 1970-01-01
      • 2021-06-24
      相关资源
      最近更新 更多