使用运行时 DLL (/MD) 避免与 dll 的运行时依赖

Avoid runtime dependency with a dll using runtime DLL (/MD)

我们使用 VS2012,并且构建了一个依赖 运行time DLL (/MD) 的 dll。 这个dll被用在很多不同的项目中,不能轻易改变。

我们还有一个小型启动器可执行文件,它必须能够 运行 在新安装的系统上,因此没有 运行 时间安装。它与 运行 时间 (/MT) 静态链接。

现在这个exe依赖于上面的dll。

原样,exe 未构建 [1]。我观察到通过忽略 MSVCRT (/NODEFAULTLIB:"MSVCRT.lib") 构建它解决了 [1],但产生了 [2]。 在 "force symbol references" 中添加报告为错误的少数符号(例如 /INCLUDE:"_strncpy")使构建成功。

然而,使用 Dependency Walker 检查生成的 exe 显示通过我们的 dll 对 运行time DLL [3] 的依赖。我确认字符串 [3] 存在于其中。尝试 运行 全新安装的 Vista 上的 exe 失败(错误表明 [3] 中的 DLL 丢失)。 我担心这是不可能的,而且我还没有找到任何表明它是可能的信息。

静态链接的 exe 能否为动态链接的 dll 提供 运行时间函数?如果是,如何?

谢谢

参考文献:

  1. 1>MSVCRT.lib(MSVCR110.dll):错误 LNK2005:_sprintf 已在 libcmt.lib(sprintf.obj)
  2. 中定义
  3. 错误 LNK2001:无法解析的外部符号 __imp__strncpy
  4. MSVCP110.dll, MSVCR110.dll

我们最终将 dll 构建设置更改为 /MT。 我不知道还有什么其他方法可以解决这个问题。

如果您的 .exe 需要 运行 干净 OS,它不能依赖任何动态链接的 DLL,因为这些 DLL(以及 .exe)不能在没有 运行time DLL 的情况下加载。你考虑过 app-local deployment 吗?然后.exe和dll都可以用/MD构建。

可以创建可以构建为 DLL 或静态库的项目。小型启动程序可执行文件应 link 具有 DLL 项目的静态库配置。

是的,静态 linked exe 可以为 DLL 提供函数。然而,使用标准库函数这样做麻烦多于它的价值。

您需要使用 /NODEFAULTLIB 阻止 DLL 使用其自己的运行时副本进行构建。这会给你带来一堆 link 错误,因为 DLL 使用的标准库的每个部分以及一些供应商扩展现在都是未解析的外部。

这些都需要使用模块定义文件添加到 EXE 导出表中。在 EXE linking 期间将生成一个导入库。然后该导入库将提供给 DLL 以满足其外部需求,解析它们。

最终,您将只有一个运行时库副本,允许您的 EXE 和 DLL 共享库对象,例如 FILE* 和堆(因此您可以在一个中分配,在另一个中释放其他)。但是 DLL 和 EXE 会非常紧密地耦合在一起。几乎对 DLL 的任何更改都可能破坏构建,并需要从 EXE 导出新文件来修复它。您绝对不能将 DLL 更新与 EXE 更新分开发送。

一种更简单的方法是使用延迟加载,它仍然可以减小 DLL 的大小。这样,虽然 DLL 在没有先安装运行时可再发行组件的情况下仍然无法加载,但在进程启动期间不会发生故障,并且 EXE 将有机会检查运行时是否存在并安装可再发行组件。或者诊断处理DLL加载失败

在极端情况下,EXE 可以完全避免使用标准库,确保可再发行组件的存在,然后为需要标准库运行时的所有复杂逻辑调用延迟加载 DLL。

在后一种情况下,由于 EXE 未使用运行时的 DLL 版本,因此您无法在 EXE 和 DLL 之间共享标准库对象。但是耦合要松散得多。我认为这是一个值得做出的权衡。