事实上,对于所有运行 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 中实现应用程序特定功能的模块
可以部署此功能的更新,而无需最终用户
重新安装应用程序。