【发布时间】:2018-03-06 03:44:18
【问题描述】:
当(非托管)Win32 程序(或其他 DLL)调用(非托管)Win32 DLL 时,我的理解是存在许多可能导致问题/崩溃的潜在不兼容性。
例如,如果程序 P 调用 DLL D,并且 P 使用 Visual Studio 2013 编译以针对 Windows SDK 版本 8,而 D 使用 Visual Studio 2017 编译以针对 Windows SDK 版本 10,我的理解是他们将访问不同的 msvc 运行时 DLL,这可能会导致问题。例如,如果 D 使用 new 分配内存并将其传递回 P,而 P 尝试将其传递给 delete,则会发生崩溃,因为 P 和 D 使用两个不同的运行时,每个运行时都维护自己的堆。
类似地,如果 P 是使用运行时类型信息 (RTTI) 构建的,而 D 不是,我的理解是,当 P 分配一个类实例(分配给每个在公共.h 文件)并将其传递给 D,因为虚函数表和/或结构字段之间的填充存在差异。
我正在尝试了解可能存在哪些其他不兼容问题。理想情况下,我想找到一个完整的列表。以下是我想到的一些可能性:
结构成员对齐(类似于 RTTI 问题)
使用多字节字符集与使用 Unicode 字符集(如果传递/返回字符串对象可能会导致问题?)
省略(相对于不省略)帧指针(或者可能不适用,因为跨程序/DLL 的函数调用机制与此标志相关的内部函数调用机制不同到?)
启用(或禁用)C++ 异常(如果它们都在启用异常的情况下构建并使用相同的运行时,则异常处理跨 DLL 调用工作?)
其他?
编辑
我问这个问题是出于普遍的好奇心,但也因为我在程序中使用 DLL 时遇到了随机堆损坏,我试图找出可能是什么问题。
我的问题原来是我正在链接一个过时的 DLL 导入库。我不确定为什么程序启动时没有错误,以及为什么它基本上运行正常但间歇性堆损坏。我相信只有在新 DLL 提供旧 DLL 导入库提供的功能的超集时,它才能无错误地启动。然后我不确定该机制是否是 C/C++ 运行时库中的不匹配,或者可能是函数参数的更改而没有函数签名的重大更改?
无论如何,我想可以将针对过时的 DLL 导入库的链接添加到列表中,尽管与提到的其他错误相比,这是一个不那么无辜的错误。
【问题讨论】:
-
MBCS 与 Unicode 字符串在 Windows 上不会成为问题,如果您遵循 Win32 约定,将 char*/string 用于 MBCS,wchar*/wstring 用于 Unicode (UTF-16)。
-
您也可以在 DLL 提供的接口中遇到不兼容问题,例如系统具有 DLL 的 1.0 版本但程序是针对 2.0 编译的,您需要安装 2.0 才能使程序工作。在 Windows 上,这是本机并排装配系统应该提供帮助的东西,但结果证明它已经足够痛苦,它似乎几乎被抛弃了(CRT 不再是一个并排装配,例如)。
-
@SornelHaetir,谢谢。是的,我主要是在考虑难以找到、不一致的崩溃,这与内存等方面的分歧有关(尽管我的问题没有清楚地表明这一点)。在您的情况下,程序将完全无法加载,或者在您尝试 GetProcAddress() 时崩溃,对吧?
标签: c++ c windows dll compatibility