C++动态库编译/链接
我知道,如果我将我的 C++ 程序链接到使用不同版本的 Visual Studio 构建的动态库 (DLL),由于二进制兼容性问题,它将无法工作。 (我在 Boost 库以及 VS 2005 和 2008 中都经历过这种情况)
但我的问题是:这对于所有版本的 MSVS 都是如此吗?这也适用于静态库(LIB)吗?这是 GCC & 的问题吗? Linux 也可以吗?最后,在 VS 中链接到用 MinGW 构建的 DLL 怎么样?
顺便问一下,除了跨平台或跨编译器之外,为什么同一编译器(VS)的两个版本不能兼容?
I know that if I link my c++ program to a dynamic library (DLL) that was built with a different version of Visual Studio, it won't work because of the binary compatibility issue.
(I have experienced this with Boost library and VS 2005 and 2008)
But my question is: is this true for all versions of MSVS? Does this apply to static libraries(LIB) as well? Is this an issue with GCC & Linux as well? and finally how about linking in VS to a DLL built with MinGW?
By the way aside from cross-platform or cross-compiler, why can't two version of the same compiler(VS) be compatibile?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我不记得曾经见过 MS 更改 ABI,因此技术上不同版本的编译器将产生相同的输出(给出相同的标志(见下文))。
因此我不认为这不是 Dev Studio 中的不兼容,而是 Boost 中的变化。
不同版本的 boost 不向后兼容(在二进制、源代码中它们是向后兼容的)。
我不相信有问题。现在,如果您使用不同的标志,则可能会使目标文件不兼容。这就是为什么调试/发布二进制文件被构建到单独的目录中并链接到不同版本的标准运行时。
您必须链接正确的静态库。但是,一旦静态库出现在您的代码中,它就会卡在那里,所有已解析的名称都不会在以后重新解析。
是的。 GCC 已经多次破坏了 ABI 中的向后兼容性(几次是故意的(有些是错误的))。这不是一个真正的问题,因为 Linux 上的代码通常作为源代码分发,你在你的平台上编译它,它就会工作。
抱歉我不知道。
充分优化的代码对象可能会被压缩得更多,因此对齐方式会有所不同。其他编译器标志可能会影响生成与其他二进制对象不兼容的代码的方式(更改调用函数的方式(堆栈上的所有参数或寄存器中的某些参数))。从技术上讲,只有使用完全相同的标志编译的对象才应该链接在一起(从技术上讲,它比这更宽松,因为很多标志不会影响二进制兼容性)。
请注意,某些库是与同一库的多个版本一起发布的,这些版本以不同的方式编译。通常,您可以通过末尾的扩展名来区分库。在我的上一份工作中,我们使用了以下约定。
I do not remember ever seeing MS changing the ABI, so technically different versions of the compiler will produce the same output (given the same flags (see below)).
Therefore I don't think this is not incompatibilities in Dev Studio but changes in Boost.
Different versions of boost are not backwards compatible (in binary, source they are backward compatible).
I don't believe there is a problem. Now if you use different flags you can make the object files incompatible. This is why debug/release binaries are built into separate directories and linked against different versions of the standard run-time.
You must link against the correct static library. But once the static library is in your code it is stuck there all resolved names will not be re-resolved at a later date.
Yes. GCC has broken backwards compatability in the ABI a couple of times (several on purpose (some by mistake)). This is not a real issue as on Linux code is usually distributed as source and you compile it on your platform and it will work.
Sorry I don't know.
Well fully optimized code objects may be compressed more thus alignment is different. Other compiler flags may affect the way code is generated that is incompatible with other binary objects (changing the way functions are called (all parameters on the stack or some parameters in registers)). Technically only objects compiled with exactly the same flags should be linked together (technically it is a bit looser than that as a lot of flags don't affect the binary compatibility).
Note some libraries are released with multiple versions of the same library that are compiled in different ways. You usually distinguish the library by the extension on the end. At my last job we used the following convention.
如果正确构建,DLL 应该与编程语言和版本无关。您可以链接到使用 VB、C、C++ 等构建的 DLL。
您可以使用 dependency walker 来检查导出的dll中的函数。
If properly built, DLLs should be programming-language and version neutral. You can link to DLLs built with VB, C, C++, etc.
You can use dependency walker to examine the exported functions in the dll.
回答你的部分问题,GCC/Linux 不存在这个问题。至少,不那么频繁。 libstdc++ 和 glibc 是 GNU 系统上的标准 C++/C 库,这些库的作者努力避免破坏兼容性。 glibc 几乎总是向后兼容,但 libstdc++ 过去曾多次破坏 ABI,并且将来可能会再次破坏。
与 C 相比,用 C++ 编写稳定的 ABI 非常困难,因为 C++ 中的自动功能剥夺了维护 ABI 所需的一些控制。特别是当您进入模板和内联函数时,某些代码会嵌入到您的应用程序中,而不是保留在共享库中。这意味着如果不重新编译应用程序,对象的结构就永远不会改变。
实际上,这在 Windows 上并不是什么大问题。如果 Microsoft 让 MSI 安装程序知道如何在安装需要它们的应用程序时从 Windows Update 获取 Microsoft 提供的 DLL,那就太棒了,但只需将可再发行组件添加到 InnoSetup 生成的安装程序就足够了。
To answer part of your question, GCC/Linux does not have this problem. At least, not as often. libstdc++ and glibc are the standard C++/C libraries on GNU systems, and the authors of those libraries go to efforts to avoid breaking compatibility. glibc is pretty much always backward compatible, but libstdc++ has broken ABI several times in the past and probably will again in the future.
It is very difficult to write stable ABIs in C++ compared to C, because the automatic features in C++ take away some of the control you need to maintain an ABI. Especially once you get into templates and inline functions, where some of the code gets embedded in your application rather than staying contained in the shared library. That means that the object's structure can't ever change without requiring a recompilation of the application.
In practice, it isn't a huge deal on Windows. It would be fantastic if Microsoft just made the MSI installer know how to grab Microsoft-provided DLLs from Windows Update when an app is installed that needs them, but simply adding the redistributable to an InnoSetup-generated installer works well enough.