为什么您认为编译时链接到动态库会增加 EXE 大小?我相信你被一些糟糕的术语选择误导了,这些术语从很久以前就用于 Windows 编程。让我们更好地使用相对术语“早期绑定”和“后期绑定”来代替应该搜索过程名称、编译器/加载器或程序员的自定义代码的选择。
使用早期绑定(又名静态链接到动态库)您的 EXE 包含值(在特殊表中):
.
...等等。
现在,当您将其转换为运行时加载(针对动态库的动态链接)时,它看起来像
VarH1 := SafeLoatLibrary(DLL1 Name);
if Error-Loading-DLL then do-error-handling;
Var1234 := GetProcAfdress(VarH1, "aaaaa");
if Error-Searching-For-Function then do-error-handling;
Var5678 := GetProcAfdress(VarH1, "bbbbb");
if Error-Searching-For-Function then do-error-handling;
等等。
显然,在后一种情况下,您的 EXE 包含所有这些值,就像在第一种情况下一样,但更重要的是 - 它包含大量处理这些值的代码,而这在以前是不存在的。
因此,虽然 EXE 的大小差异对于今天的内存大小来说并不是很大,但它仍然有利于早期绑定(针对动态库的静态编译)。
那么后期绑定有什么好处呢?例如,您可以从不同的路径加载不同的 DLL,在运行时由配置确定 - DLL Hell 的灵活性和避免(有趣的是,避免 DLL Hell 的概念与体积节省的概念相反)。如果 DLL 加载失败而静态绑定的 EXE 将无法加载,您可以使您的应用程序使用有限的功能工作 - 优雅降级概念。至少你可以为用户提供比 Windows 更好的、充满语义的、错误消息。
最后一句话,你从哪里得到 EXE 大小的概念。我相信你从谈论中误会了——注意!-针对静态库的静态链接。也就是说,OBJ/LIB/DCU 文件不是分发的一部分,而只是临时代码容器,最终会在单一的 EXE 中占据一席之地。那么是的 - 那么您的 EXE 本身就拥有所有这些库,因此会变得更大。然而,这种情况与动态库无关 - DLL。
以前选择的措辞在两个密切相关的主题中过度使用了静态/动态术语:如何加载库(编译时与运行时)以及库内的函数如何定位(或绑定)。由开发人员的自定义编码 ro 由某些操作系统提供或在源代码的第一行开始执行之前编译器提供的工具集方式)。
由于这种模糊性,那些接近但不同的概念开始重叠,有时这会导致完全混乱。
现在,在现代 Windows 版本中,更多的静态链接可能会给您带来什么。那是WinSxS 文件夹Novadays Windows 倾向于保留每个系统 DLL 的多个版本,您的程序可能会要求它的特定版本(而在System32文件夹中会有您的程序可能不习惯的最新版本。然后你可以制作一个特殊的 MANIFEST 资源并将其编译为 EXE,要求 Windows 加载不是名称的 DLL,而是按名称+版本。您也可以通过动态加载复制该功能,但使用 Windows 提供的工具集要容易得多。
现在,您可以决定哪些选项对您的特定情况重要或不重要,并做出更明智的选择。
HTH。