潜在的 dll 兼容性问题的总结?

Posted

技术标签:

【中文标题】潜在的 dll 兼容性问题的总结?【英文标题】:summary of potential dll compatibility issues? 【发布时间】: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() 时崩溃,对吧? 【参考方案1】:

一个非常常见的错误是在 dll-interfaces 中使用标准库内容或其他编译器实现/版本相关功能。 这通常只有在双方(dll 及其用户)使用相同版本的编译器时才有效,即使这样,当其中一方启用 DEBUG 而另一方使用 NDEBUG 构建时,也可能存在不兼容性。

仅在 dll 接口中使用与 c 兼容的类型等。

【讨论】:

为了证明你的观点,我有一个用 Visual Studio 2008 构建的 DLL,它可以在用 VS 2017 编译的应用程序中正常工作。这是因为导出的函数指定 C compatible 或Windows API 类型作为参数。

以上是关于潜在的 dll 兼容性问题的总结?的主要内容,如果未能解决你的问题,请参考以下文章

5个技巧躲避潜在的浏览器兼容性问题

win8下安装VC6出现兼容性问题的解决办法

增加 Android 目标 SDK 时如何识别潜在的不兼容问题

.lib 和 .dll 向后兼容性

ISE14.7兼容性问题集锦

win7出现故障模块kernelbase.dll