动态链接到库的一个好处是,当调用该库中的函数时,将其加载到程序的虚拟地址空间中,然后调用该函数。静态链接会加载整个可执行文件,从而占用空间。
在Windows上,当加载程序时,所有函数导入都将在调用程序入口点之前解决。例如:kernel32.dll!VirtualFree
。加载所有需要的库,然后调用程序的入口点。
这与静态链接的可执行文件有何不同?如果同时加载所有引用的库,是否会占用相同的空间?有什么好处?请帮助我理解。
就事实而言,它是不是有必要对所有在其上的Windows应用程序依赖它启动时要加载的DLL。从Visual C ++ 6.0(1998)开始,MS链接器支持该/DELAYLOAD
选项,该选项推迟DLL的加载,直到且除非调用其导出之一。
默认行为是在启动时加载DLL。我假设您想知道默认行为如何与在内存占用空间以及更一般的意义上链接静态库之间进行权衡。
假定具有相同实现的相同API作为静态库libfoo.lib
和动态库构建libfoo.dll
。
只要libfoo.dll
在给定的时间仅需要一个程序,那么与该程序静态链接时在同一时间所消耗的内存至少相同libfoo.lib
。
实际上,加载DLL的程序版本比与静态库链接的版本消耗的内存更多。这是因为第一次加载DLL时,整个DLL都加载到了内存中。但实际上,事实并非并非如此,当程序与静态库链接时,整个静态库必须合并到可执行文件中。一个静态库是简单对象文件的归档,从该连接器在默认情况下只提取定义由程序引用符号,链接那些他们到程序中,忽略其它。因此,如果程序不需要将所有目标文件存档在libfoo.lib
,则静态链接libfoo.lib
所需的内存将小于动态链接所需的内存libfoo.dll
。
但是,一旦同时需要多个运行程序,则内存成本开始开始向DLL倾斜libfoo.dll
。这是因为DLL由不同的代码和数据部分组成,加载器可以分别加载它们。每个需要的并发程序都需要libfoo.dll
拥有自己的DLL数据副本,但是它们都可以执行其代码的同一副本。在libfoo.dll
为第一个需要它的程序加载了代码和数据部分之后,加载器只需要为需要的并发程序加载其数据的新副本。
因此,当我们考虑整个运行系统的内存占用量时,其中许多并发进程可能需要单个库提供的服务,因此在DLL中而不是静态库中实现此类服务是一种经济的策略。
DLL的主要目的是以这样一种方式提供服务:无论有多少并发程序正在执行它,都仅需加载实现代码的一个副本。
但是它们还有另一个重要的好处,即使对于只可能被一个应用程序使用的库也是如此。制作新版本的foo
库(提供错误修复或增强功能)后,可以将此版本部署到已与静态库链接的程序中的唯一方法libfoo.lib
是重新链接,重新分发并重新安装所有这些程序。但是只要新版本的libfoo
保留了现有的API,与链接的程序就根本不需要做任何事情libfoo.dll
。只需分发和安装的新版本libfoo.dll
,这些程序将在下次运行时加载它。应用程序架构师可以选择实现特定于应用程序的模块 精确地在DLL中提供功能,以便可以部署此功能的更新,而不必要求最终用户重新安装该应用程序。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句