如何避免Windows上多个CRT版本的问题(dll地狱重访?)
How to avoid problems with multiple CRT versions on Windows (dll hell revisited?)
我很感激以前也有人问过类似的问题,但阅读这些问题时,没有一个能完全解决我们的问题,所以我想我会寻求任何见解。
[TL;DR]版本:
是否可以/容易地为VS2005 CRT创建一个填充程序dll,然后将所有调用委派给VS2013 CRT?
降级VS2013版本以便使用VS2005 CRT是否更容易?
还是这两种想法都很疯狂?
我们的情况:
我们的C++应用程序是使用现代版本的C++编译器构建的(VS2013,gcc 4.8取决于目标平台)-我们使用的一些依赖项将需要现代版本,因为它们使用C++11。
我们的应用程序还使用运行时链接(.dll或.so)来打包各种应用程序组件。
在windows上,为了简化生活,我们使用/MD(或/MDd用于调试)进行编译,即使用多线程版本在dll中使用CRT-我们构建的任何依赖项都会重新编译为使用相同的CRT。
对所有依赖项使用相同的CRT(在单独的dll中)意味着,如果在一个dll中分配内存并在另一个dll释放内存,则可以避免问题,因为使用了相同的堆。
我们的问题
我们有一个依赖项,它是由第三方提供的(我不会在这里点名羞辱他们,但你知道你是谁!),作为预编译的dll/so,而不是作为源。
这是在Windows上使用VS2005(MSVC8)编译的,并使用MSVC8 crt。
他们以前版本的这种依赖关系运行良好。他们对这个依赖关系的api正确地处理了内存的分配和取消分配,所以即使它使用的是与我们应用程序的其他部分不同的CRT版本,它也没有问题。
不幸的是,他们的新版本("改进"!)在他们的api中大量使用了C++模板——这些模板在我们的调用代码中扩展,并导致试图从我们的调用码中删除在其dll中分配的内存。由于这两个区域使用不同的堆,这是非常有问题的。
可能的解决方案:
为了解决这个问题,我们可以看到以下可能的解决方案
1] 让供应商重写(我们已经要求过了,这是一个长期的解决方案,但在一段时间内不会发生)
2] 让供应商使用VS2013重新编译,这样我们双方都有相同的CRT(只是显然不会发生——已经要求了)。
3] 我们的所有代码都使用VS2005CRT(我们不能简单地使用VS2005来构建我们的代码,因为我们需要C++11支持)
4] 对第三方dll所期望的VS2005 CRT进行填隙,即构建看起来像VS2005 CRT但实际上使用的是VS2013 CRT的东西。
5] 包装第三方dll-即构建一个用VS2005编译的dll,其中包含对第三方依赖项的所有调用-并提供正确的内存处理,使其与我们的其他(使用VS2013 CRT的)dll 一起工作
最后是问题:
选项5]可能是工作量最大的(但成功的可能性最大)——基本上是选项1],但在我们的控制之下,所以我们不必等待第三方。
不过,在采用这条路线之前,我想我会问一下其他人是否做过类似于3]或4]的事情,或者其他我们没有想到的解决方案。
选项4](构建一个填充版本的CRT)似乎可能是最简单的,因为我认为VS2013 CRT中已经完成了许多向后兼容性工作——这只是一个找出细节并将2005版本的调用转发到2013版本的例子——在许多情况下,我认为甚至签名都是相同的,所以只是一个简单的条目。
然而,当我在谷歌上查看时,我找不到任何人为CRT版本不兼容问题构建填充程序dll的例子——所以这可能比我想象的要困难得多(或者我的谷歌功能严重缺乏)。
所以我想我会问是否有人做过类似的事情/知道为什么这是一个非常愚蠢的想法吗?
没有合理的方法可以实现匀场。
破坏交易的因素是STL实现发生了变化,而这些都是模板。几乎可以肯定的是,DLL混合了对VS2005STL的内联和非内联调用。如果将VS2005换成VS2013 CRT,则它们的DLL将混合使用内联VS2005和非内联VS2013调用。这无疑是一场灾难。这是假设VS2013CRT甚至具有所需的非内联版本。
也就是说,您可以在代码中提供自己的new
和delete
。这些可以转发到相应的VS2005版本,您可以在运行时通过GetProcAddress
检索这些版本。这可能也许就足够了——没有保证。
- 挂起和取消挂起一个文件DLL
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 导入库可以跨dll版本工作吗
- 从C++dll访问C#中的一行主要参数
- 链接到自行创建的dll失败
- 为什么使用 P/Invoke 调用 dll 时,某些计算机中的 LoadLibrary 失败?
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 如何指定我希望我的LIB链接到的DLL文件?-Visual Studio 2019
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- C++:将外部库链接到dll库
- 在 Windows 上,是否可以让 dll 在不使用 PATH 环境变量的情况下在另一个文件夹中查找依赖项?
- 不同的Visual Studio版本中缺少.dll
- 从DLL中删除类的实例
- 如何包装第三方DLL在R中使用
- 使用c#访问c++dll中带有char*参数的函数时发生AccessViolationException
- 系统.将数组移交给c#中动态加载的c++DLL时发生AccessViolationException
- 为什么导入Mixed native/CLR lib.dll的本机C++应用程序没有在Mixed lib.dll中的外部变
- 当我使用 C++ 中的 C# dll 来使用 Selenium 时,存在异常处理问题
- 如何跟踪使用过的DLL(是不是所谓的DLL地狱?)
- 如何避免Windows上多个CRT版本的问题(dll地狱重访?)