假设A是主程序(自己写的代码),A调用了动态库B(第三方提供),而A和B均引用了模块C(另一个DLL),但A和B对应C的不同版本且无法兼容。此时将哪一个版本的模块C引入至运行路径,均会导致程序无法正常运行。
例如,Qt的动态库。Qt5Core.dll,不管Qt 5.9还是Qt 5.15,都是同一个名字,不能混用
DLL地狱问题,C++ two libraries depend on same lib but different versions?
一位博主的总结:c++同名dll和dll中同名函数加载问题
最简单的解决办法是让模块A和模块B均基于同一版本的模块C,但实践中有难度
一种可能的办法(未验证):设法延迟模块B的加载时机,在其加载前将模块A的运行路径从系统路径中剔除,并添加模块B的路径
另一种办法是修改动态库(仅限动态库)的名称,让程序加载不同名称的库文件
stackflow上有个贴讨论了这种方案:Can I use two incompatible versions of the same DLL in the same process?
如果动态库是通过显式加载的,那只要直接改dll的文件名和LoadLibrary
的路径即可
如果动态库是通过隐式加载,那就需要修改dll文件的导入列表(Import),可以通过CFF Explorer编辑DLL文件,用CFF打开调用DLL的程序,修改"Import Directory"右边表格里的Module name
如我这里是修改Qt5Cored.dll为QtCoredX.dll,注意名字长度必须跟原来一致
然后把dll重命名,之后的确调用的就是修改后的dll文件,但会提示“无法定位入口点XXXXX”,说明函数地址有问题,应该还要改别的,此处没有深入研究下去
TODO
又试了一种土办法,强行修改lib文件,实测可以,但需要有源码重新编译
中途编译报错error LNK2001 ... __IMPORT_DESCRIPTOR_XXXX
,这是因为没改彻底,如一开始只替换了"Qt5Cored.dll"关键字,还要替换"Qt5Cored"