为什么动态链接导入(在 Windows 中)总是在应用程序启动时加载?
Why do dynamically linked imports (in Windows) always load at application start up time?
动态链接到库的一个好处是,当调用该库中的函数时,它会加载到程序的虚拟地址 space 中,然后调用该函数。静态链接加载整个可执行文件,占用 space.
在 windows 上,当程序正在加载时,所有函数导入甚至在调用程序入口点之前就已解析。例如:kernel32.dll!VirtualFree
。加载所有需要的库,然后调用程序的入口点。
这与静态链接的可执行文件有何不同?如果一次加载所有引用的库,它不会占用相同数量的 space 吗?有什么好处?请帮助我理解。
事实上,不是对于所有 Windows
应用程序依赖于在启动时加载。自 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
一个 运行ning 程序同时需要 libfoo.dll
。那是
因为 DLL 由加载程序可以单独加载的不同代码和数据部分组成。
每个需要 libfoo.dll
的并发程序都需要有自己的副本
DLL 的 data,但它们都可以执行其 code 的相同副本。后
libfoo.dll
- 代码和数据部分 - 已首次加载
需要它的程序,加载程序只需要加载其 data 的新副本
对于需要它的任何更多并发程序。
所以当我们考虑整个 运行ning 系统的内存占用时,其中
许多并发进程可能需要单个库提供的服务,
在 DLL 而不是静态库中实现此类服务是经济的
策略。
DLL 的主要目的是以一种只有一个副本的方式提供服务
无论有多少并发程序,都必须加载的实现代码
正在执行它。
但是它们还有另一个重要的好处,即使对于图书馆来说也是如此
只可能被一个应用程序使用。 foo
库的新版本发布时
制作,提供错误修复或增强功能,这是部署此版本的唯一方法
与静态库链接的程序 libfoo.lib
是
重新链接、重新分发和重新安装所有这些程序。但只要是新的
libfoo
的发布保留了现有的 API,根本不需要做任何事情
与 libfoo.dll
链接的程序。只需要
分发并安装 libfoo.dll
的新版本,这些程序将
下次他们 运行 时加载它。应用程序架构师可以选择
在 DLL 中精确地实现 特定于应用程序 功能的模块
可以部署此功能的更新,而无需最终用户
重新安装应用程序。
动态链接到库的一个好处是,当调用该库中的函数时,它会加载到程序的虚拟地址 space 中,然后调用该函数。静态链接加载整个可执行文件,占用 space.
在 windows 上,当程序正在加载时,所有函数导入甚至在调用程序入口点之前就已解析。例如:kernel32.dll!VirtualFree
。加载所有需要的库,然后调用程序的入口点。
这与静态链接的可执行文件有何不同?如果一次加载所有引用的库,它不会占用相同数量的 space 吗?有什么好处?请帮助我理解。
事实上,不是对于所有 Windows
应用程序依赖于在启动时加载。自 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
一个 运行ning 程序同时需要 libfoo.dll
。那是
因为 DLL 由加载程序可以单独加载的不同代码和数据部分组成。
每个需要 libfoo.dll
的并发程序都需要有自己的副本
DLL 的 data,但它们都可以执行其 code 的相同副本。后
libfoo.dll
- 代码和数据部分 - 已首次加载
需要它的程序,加载程序只需要加载其 data 的新副本
对于需要它的任何更多并发程序。
所以当我们考虑整个 运行ning 系统的内存占用时,其中 许多并发进程可能需要单个库提供的服务, 在 DLL 而不是静态库中实现此类服务是经济的 策略。
DLL 的主要目的是以一种只有一个副本的方式提供服务 无论有多少并发程序,都必须加载的实现代码 正在执行它。
但是它们还有另一个重要的好处,即使对于图书馆来说也是如此
只可能被一个应用程序使用。 foo
库的新版本发布时
制作,提供错误修复或增强功能,这是部署此版本的唯一方法
与静态库链接的程序 libfoo.lib
是
重新链接、重新分发和重新安装所有这些程序。但只要是新的
libfoo
的发布保留了现有的 API,根本不需要做任何事情
与 libfoo.dll
链接的程序。只需要
分发并安装 libfoo.dll
的新版本,这些程序将
下次他们 运行 时加载它。应用程序架构师可以选择
在 DLL 中精确地实现 特定于应用程序 功能的模块
可以部署此功能的更新,而无需最终用户
重新安装应用程序。