我知道,如果我将我的c++程序链接到用不同版本的Visual Studio构建的动态库(DLL),由于二进制兼容性问题,它将无法工作。(我在Boost库和VS2005和2008中经历过这种情况)
但我的问题是: MSVS的所有版本都是这样的吗?这是否也适用于静态库(LIB)?这也是GCC和Linux的问题吗?最后,如何在VS中链接到用MinGW构建的动态链接库?
顺便说一下,除了跨平台或跨编译器之外,为什么同一编译器(VS)的两个版本不能兼容?
发布于 2011-04-23 02:05:15
嗨。我知道,如果我将我的c++程序链接到用不同版本的Visual Studio构建的动态库(DLL),由于二进制兼容性问题,它将无法工作。(我在Boost库和VS2005和2008中经历过这种情况)
我不记得曾经见过MS改变ABI,所以技术上不同版本的编译器将产生相同的输出(给定相同的标志(见下文))。
因此,我不认为这不是Dev Studio的不兼容,而是Boost的变化。
不同版本的boost不能向后兼容(在二进制版本中,它们是向后兼容的)。
但我的问题是:所有版本的
都是这样的吗?
我不认为有什么问题。现在,如果您使用不同的标志,您可以使目标文件不兼容。这就是为什么调试/发布二进制文件被构建到单独的目录中,并针对不同版本的标准运行时进行链接。
这是否也适用于静态库(LIB)?
您必须链接到正确的静态库。但是,一旦静态库在您的代码中,它就卡在那里了,所有解析的名称在以后都不会被重新解析。
这也是
& Linux的问题吗?
是。GCC已经在ABI中破坏了几次向后兼容性(有几次是故意的(有些是错误的))。这不是一个真正的问题,因为在Linux上,代码通常是作为源代码分发的,您可以在您的平台上编译它,它将会工作。
,最后,如何在VS中链接到用MinGW构建的动态链接库?
对不起我不知道。
顺便说一下,除了跨平台或跨编译器之外,为什么同一编译器(VS)的两个版本不能兼容?
完全优化的代码对象可能会被更多地压缩,因此对齐是不同的。其他编译器标志可能会影响与其他二进制对象不兼容的代码生成方式(更改函数的调用方式(堆栈上的所有参数或寄存器中的某些参数))。从技术上讲,只有使用完全相同的标志编译的对象才应该链接在一起(从技术上讲,它比这要松一点,因为许多标志不会影响二进制兼容性)。
注有些库是随同一个库的多个版本一起发布的,这些版本是以不同的方式编译的。通常通过库末尾的扩展名来区分库。在我的上一份工作中,我们使用了以下约定。
libASR.dll // A Sincgle threaded Relase version lib
libASD.dll // A Single threaded Debug version
libAMR.dll // A Multi threaded Release version
libAMD.dll // A Multi threaded Debug version发布于 2011-04-23 00:36:35
如果构建正确,DLL应该是编程语言和版本无关的。您可以链接到使用VB、C、C++等构建的DLL。
可以使用dependency walker检查dll中导出的函数。
发布于 2011-04-23 01:30:21
为了回答你的部分问题,GCC/Linux没有这个问题。至少,不是那么频繁。libstdc++和glibc是GNU系统上的标准C++/C库,这些库的作者努力避免破坏兼容性。glibc几乎总是向后兼容的,但是libstdc++在过去已经破坏了ABI几次,将来可能还会再次破坏。
与C相比,用C++编写稳定的ABI非常困难,因为C++中的自动特性剥夺了维护ABI所需的一些控制。尤其是当你开始使用模板和内联函数时,其中一些代码会嵌入到你的应用程序中,而不是一直包含在共享库中。这意味着在不重新编译应用程序的情况下,对象的结构永远不能改变。
实际上,这在Windows上并不是什么大问题。如果微软只是让MSI安装程序知道如何在安装需要的应用程序时从Windows Update中获取Microsoft提供的DLL,那就太好了,但只需将可再发行的文件添加到InnoSetup生成的安装程序中就足够了。
https://stackoverflow.com/questions/5757566
复制相似问题