我们使用VS2012,并且构建了一个依赖于运行时DLL(/ MD)的DLL。 这个DLL用于许多不同的项目,不能轻易改变。
我们还有一个小的启动器可执行文件,必须能够在新安装的系统上运行,因此没有安装运行时。它与运行时(/ MT)静态链接。
现在这个exe取决于上面的dll。
原样,exe没有构建[1]。我观察到通过忽略MSVCRT(/NODEFAULTLIB:“MSVCRT.lib”)来构建它解决了[1],但产生了[2]。 在“强制符号引用”中添加少量符号报告为错误(例如/ INCLUDE:“_ strncpy”)使构建成功。
但是,使用Dependency Walker检查生成的exe会通过我们的dll显示对运行时DLL [3]的依赖性。我确认字符串[3]存在于其中。试图在干净安装的Vista上运行exe失败(错误表示缺少来自[3]的DLL)。 我担心这是不可能的,我没有发现任何暗示它的信息。
静态链接的exe可以为动态链接的dll提供运行时函数吗?如果是,怎么样?
由于
参考文献:
答案 0 :(得分:1)
是的,静态链接的exe可以为DLL提供函数。但是,使用标准库函数执行此操作比使用它更麻烦。
您需要使用/NODEFAULTLIB
停止使用自己的运行时副本构建DLL。这将导致一堆链接错误,因为DLL使用的标准库的每个部分以及一些供应商扩展现在都是未解析的外部。
需要使用模块定义文件将其中的每一个添加到EXE导出表中。 EXE链接期间将生成导入库。然后,该导入库将提供给DLL以满足其外部,解决它们。
最后,你只有一个运行时库的副本,允许你的EXE和DLL共享库对象,如FILE*
和堆(所以你可以在一个中分配,在另一个中免费) 。但是DLL和EXE会非常紧密地耦合在一起。几乎任何DLL的更改都可能破坏构建,并需要EXE的新导出来修复它。您肯定无法与EXE的更新分开发送DLL的更新。
一种更简单的方法,即仍然保持DLL大小,将使用延迟加载。这样,虽然DLL仍然无法在没有首先安装运行时可再发行组件的情况下加载,但在进程启动期间不会发生故障,并且EXE将有机会检查运行时是否存在并安装可再发行组件。或诊断并处理DLL加载失败。
在极端情况下,EXE可以完全避免使用标准库,确保可再发布组件的存在,然后为需要标准库运行时的所有复杂逻辑调用延迟加载DLL。
在后面这些情况下,因为EXE没有使用运行时的DLL版本,所以不能在EXE和DLL之间共享标准库对象。但耦合更松散。我认为这是一个值得做出的权衡。
答案 1 :(得分:0)
我们最终将dll构建设置更改为/ MT。 我不知道有任何其他方法可以解决这个问题。
答案 2 :(得分:0)
如果您的.exe需要在干净的操作系统上运行,它不能依赖任何动态链接的DLL,因为这些DLL(以及.exe)在没有运行时DLL的情况下无法加载。你考虑过app-local deployment了吗?然后.exe和dll都可以用/ MD构建。
答案 3 :(得分:0)
可以创建可以构建为DLL或静态库的项目。小型启动程序可执行文件应链接到DLL项目的静态库配置。