Visual C++ 的 STL 实现的主要作者 Stephan T. Lavavej 在这个Reddit 线程中列出了规则:
以下是准确的规则:
如果您包含任何 C++ 标准库标头,则必须遵守其规则,并且我们故意破坏主要版本之间的二进制兼容性(但在修补程序和服务包之间保留它)。任何表示更改(包括但不限于添加/删除数据成员)都会破坏二进制兼容性,这就是为什么总是会发生这种情况,也是我们小心翼翼地保护这一权利的原因。
[剪辑]
因此,如果您遵守 STL 的规则,则需要确保以下几点:
- 所有链接到单个二进制文件 (EXE/DLL) 的目标文件和静态库都必须使用相同的主要版本进行编译。我们添加了链接器检查,因此不匹配的 VS 2010+ 主要版本将在链接时触发硬错误,但如果涉及 VS 2008 或更早版本,我们将无法帮助您(没有时间机器)。因为这里适用 ODR,所以您确实应该对所有目标文件和静态库使用相同的工具集(即相同的服务包级别)。例如,我们修复了 VS 2010 RTM 和 SP1 之间的 std::string 内存泄漏,但如果您混合 RTM 和 SP1,生成的二进制文件可能会或可能不会受到泄漏的影响。(此外,您需要使用相同的 _ITERATOR_DEBUG_LEVEL 和发布/调试设置;我们现在对这些进行了链接器检查。)
- 如果您将多个二进制文件加载到同一个进程中,并且它们将 C++ 标准库对象相互传递,则必须使用相同的主要版本和 _ITERATOR_DEBUG_LEVEL 设置构建这些二进制文件(发布/调试也应该匹配,我忘记了您是否可以逃脱此处不匹配)。重要的是,我们无法检测到违反此规则的行为,因此您必须遵守它。
- 接口是纯 C 或 COM(或现在的 WinRT)的多个二进制文件可能在内部使用不同的主要版本,因为这些东西保证了二进制兼容性。如果您的接口涉及 C++ 核心语言(例如带有虚拟的东西),但非常小心从不提及任何 C++ 标准库类型,那么您可能没问题 - 编译器确实试图避免破坏二进制兼容性。
但是请注意,当加载到单个进程中的多个二进制文件使用不同的主要版本编译时,您几乎肯定会最终将多个 CRT 加载到您的进程中,这是不可取的。
底线 - 如果您 100% 一致地编译所有内容,您就不必担心这些东西。如果可以避免的话,不要玩混合游戏。