Windows:同时构建同一DLL的32位和64位版本

Windows: Building both 32-bit and 64-bit versions of the same DLL

本文关键字:32位 64位 版本 构建 Windows DLL      更新时间:2023-10-16

作为我新合同职位培训的一部分,我的任务是构建两个DLL和两个cppunit单元测试程序。一切顺利。

当我尝试运行其中一个单元测试程序时,我发现两个DLL(单元测试程序使用的)都混合了32位和64位元素。我下载了DependencyWalker(Dependens.exe),并跟踪DLL获取输入的问题。32位库位于名为C:\AppName\bin的目录中,64位库位于C:\AppName\bin64中。

由于DLL要到运行时(实际加载时间)才能加载,并且DLL与.exe不在同一目录中,并且PATH将这两个文件夹的搜索顺序显示为"C:\AppName\bin64;C:\AppName\bin;",因此当我尝试运行单元测试时,我收到一个错误,告诉我有64位模块与32位模块混合,并拒绝运行。我通过将bin64重命名为SAVE_bin64来解决这个问题,这样加载程序将无法找到它,默认为其他目录,并加载正确的DLL。

我的同事也接到了同样的任务。他没有这样的困难。不仅如此,我之前已经成功运行了该程序,但在使用公司安装设施安装了一些模块后遇到了这个问题。由于安装是在后台进行的,除了foo阻止我的构建外,我不知道它做了什么。

Visual Studio C++(非托管)生成过程中的某些内容在.exe中包含了足够的信息,可以让加载程序知道在哪里可以找到正确的DLL,但在我安装时却被搞砸了。

在打开Depends.exe中的"完整路径"最终发现原因之前,我对这个问题进行了广泛的研究,所以我已经了解了SxS(并排)和DLL重定向,这两种方法在这里都不相关。

所以,问题是,Windows加载程序是如何一次找到正确的DLL,而另一次却找不到;加载程序是如何在他的机器上找到正确的DLL而不是我的?

提前谢谢。

编辑后添加:

我又试了一个实验。由于我的bin64仍然重命名为SAVE_bin64,我将库(libB.dll依赖于libA.dll)和单元测试程序(都依赖于libB.dll)都构建为32位。然后,我将SAVE_bin64重命名回bin64,这样,如果加载程序完全依赖于PATH变量来定位依赖的DLL,那么由于32/64位不匹配,单元测试程序应该无法运行。然而,单元测试程序运行了,成功地在72个模块中找到了一个错误。

这表明Visual Studio 2010 C++编译器/链接器能够以某种方式将相关DLL的正确位置嵌入到可执行程序中,这样加载程序就不必依赖PATH变量来查找DLL。

这可能有助于理解Windows如何搜索dll:
MSDN:动态链接库搜索顺序

加载程序将选择它首先看到的(在搜索列表中)具有匹配名称的任何dll。DLL是64位还是32位并不重要。我很确定,如果它是一个重命名为.dll的文本文件,它甚至会尝试加载它也许你的同事把他的dll放在了系统文件夹中,或者与应用程序版本并排。

我发现处理这个问题的一个简单方法是为32位和64位的dll使用不同的名称。example32.dll和example64.dll。