Visual Studio不同版本之间的库ABI兼容性问题

13

我有两种情况。假设我有三个使用VS7.1、VS8和VS9编译的导出C++符号的共享库。我在VS9中编译了全部3个库,由于某种原因,这是有效的。我不需要重新在VS9中编译前两个库,VS9链接器就可以成功地找到符号并与它们进行链接。

现在,如果我有一个只使用C语法(extern "C")导出符号的库,是否相同呢?我听说过人们说C的ABI是标准化的,因此你可以保证在所有版本的Visual Studio中使用一个在Visual Studio 8中编译的C库。

基本上,所有这些组合令人困惑。我不确定在不同版本的Visual Studio之间链接针对C++和C库(使用相应的导入库)之间的保证。我想听听关于C和C++导入或静态库的向前/向后兼容性的普遍共识。

我提出这个问题的原因是因为我正在使用已编译Visual Studio .NET 2003(VS7.1)的闭源库。我的团队认为这将我们锁定到VS 7.1编译器,但我已经在VS8和VS9甚至VS2010中测试了这些库,它们可以很好地链接。然而,我不确定这样做的潜在危险。请注意,涉及的库有C变体和C++变体。基本上,C变体是标准C导出,而C++库是对C库的抽象,并导出类。


你可以在较新版本的Visual Studio中使用以前版本编译的二进制文件,这有点像巧合。这并不是保证的,你不应该依赖它。除非你可以获取到一个可以动态链接的二进制文件版本(即DLL),否则它真的应该将你锁定在旧版本的编译器中。如果你选择使用新版本的编译器,那么广泛的测试是完全不可避免的。 - Cody Gray
@CodyGray:我同意这是一个巧合,但既然这些编译器已经发布并且它们的工作方式已经确定,我有保证它们会正常工作。我认为我不能保证的是未来版本的VS编译器。 - void.pointer
嗯,那有一定的道理。您可以保证您经过广泛测试并验证工作的所有内容将始终继续工作。您没有任何代码将工作的保证(至少,文档没有提供)。因此,测试是必要的。虽然您可能可以在旧版本中摆脱它,但未来的发布则是一个未知数。 - Cody Gray
2个回答

4
这个问题可能不仅在于这些VS版本之间的ABI差异(调用约定等),而且还涉及到系统DLL库中已删除或更改的符号。请参见此表,以获取VS8(2005年,Windows SDK 5.0)和VS9(2008年,Windows SDK 6.0)之间系统DLL库的详细比较信息。
另请参见Windows SDK的兼容性矩阵enter image description here

我不认为Windows SDK的更改会对此产生影响,因为使用MSVC 7.1构建的闭源二进制文件将始终加载其构建时使用的MSVC 7.1运行时。 - void.pointer

2

extern "C"导出的符号与C++符号不同。C++采用名称重整(详见http://en.wikipedia.org/wiki/Name_mangling)。

C++符号的重整可能因编译器版本而异,所以在您的VS7/8/9设置中,相同的C++方法名称可能被重整为不同的名称。

基本上,你的团队是正确的-你将被锁定在用于编译库的相同主要版本的编译器中。


我如何在VS9中使用C++ VS7.1和VS8库呢? - void.pointer
根据您提供的维基百科链接,VS6-VS10共享相同的名称修饰方案,这可以解释它们为什么能够工作。因此,在这些编译器之间交换C++库是安全的。 - void.pointer
1
@RobertDailey:有一些C++库,但没有涉及标准库(实现在编译器版本之间会发生变化,这将违反ODR)。最安全的做法是在编译器版本之间坚持使用纯C导出。 - ildjarn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接