链接C ++ 17,C ++ 14和C ++ 11对象是否安全 [英] Is it safe to link C++17, C++14, and C++11 objects

查看:86
本文介绍了链接C ++ 17,C ++ 14和C ++ 11对象是否安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有三个编译对象,它们都是由相同的编译器/版本产生的:

Suppose I have three compiled objects, all produced by the same compiler/version:

  1. A使用C ++ 11标准进行编译
  2. B使用C ++ 14标准进行编译
  3. C使用C ++ 17标准进行编译

为简单起见,我们假设所有标头都是用C ++ 11编写的,仅使用语义在所有三个标准版本之间都没有改变的结构,因此任何相互依赖关系都可以通过标头包含来正确表达并且编译器没有反对.

For simplicity, let's assume all headers were written in C++11, using only constructs whose semantics haven't changed between all three standard versions, and so any interdependencies were correctly expressed with header inclusion and the compiler did not object.

这些对象是哪种组合,链接到单个二进制文件不安全吗?为什么?

Which combinations of these objects is it and isn't it safe to link into a single binary? Why?

欢迎涵盖主要编译器(例如gcc,clang和vs ++)的答案

answers covering major compilers (e.g. gcc, clang, vs++) are welcome

推荐答案

这些对象是哪种组合,链接到单个二进制文件不安全吗?为什么?

Which combinations of these objects is it and isn't it safe to link into a single binary? Why?

对于GCC ,可以安全地将对象A,B和C的任意组合链接在一起.如果它们都使用相同的版本构建,则它们是ABI兼容的,即标准版本(即-std选项)没有任何作用.

For GCC it is safe to link together any combination of objects A, B, and C. If they are all built with the same version then they are ABI compatible, the standard version (i.e. the -std option) doesn't make any difference.

为什么?因为这是我们实施的重要属性,因此我们要努力确保.

Why? Because that's an important property of our implementation which we work hard to ensure.

您遇到问题的地方是,如果将使用不同版本的GCC版本编译的对象链接在一起 ,并且在GCC对该标准的支持完成之前,您已经使用了来自新C ++标准的不稳定功能.例如,如果使用GCC 4.9和-std=c++11编译对象,而使用GCC 5和-std=c++11编译另一个对象,则会出现问题. C ++ 11支持在GCC 4.x中处于试验阶段,因此GCC 4.9和5版本的C ++ 11功能之间存在不兼容的更改.同样,如果使用GCC 7和-std=c++17编译一个对象,而使用GCC 8和-std=c++17编译另一个对象,则会遇到问题,因为GCC 7和8对C ++ 17的支持仍在试验和发展中.

Where you have problems is if you link together objects compiled with different versions of GCC and you have used unstable features from a new C++ standard before GCC's support for that standard is complete. For example, if you compile an object using GCC 4.9 and -std=c++11 and another object with GCC 5 and -std=c++11 you will have problems. The C++11 support was experimental in GCC 4.x, and so there were incompatible changes between the GCC 4.9 and 5 versions of C++11 features. Similarly, if you compile one object with GCC 7 and -std=c++17 and another object with GCC 8 and -std=c++17 you will have problems, because C++17 support in GCC 7 and 8 is still experimental and evolving.

另一方面,以下对象的任何组合都可以使用(尽管请参见以下有关libstdc++.so版本的注释):

On the other hand, any combination of the following objects will work (although see note below about libstdc++.so version):

  • 使用GCC 4.9和-std=c++03
  • 编译的对象D
  • 使用GCC 5和-std=c++11
  • 编译的对象E
  • 使用GCC 7和-std=c++17
  • 编译的对象F
  • object D compiled with GCC 4.9 and -std=c++03
  • object E compiled with GCC 5 and -std=c++11
  • object F compiled with GCC 7 and -std=c++17

这是因为在使用的所有三个编译器版本中C ++ 03支持都是稳定的,因此C ++ 03组件在所有对象之间都是兼容的.自GCC 5起,对C ++ 11的支持是稳定的,但对象D不使用任何C ++ 11的功能,而对象E和F都使用对C ++ 11的支持稳定的版本.在任何使用的编译器版本中,C ++ 17的支持都不稳定,但是只有对象F使用C ++ 17功能,因此与其他两个对象没有兼容性问题(它们共享的唯一功能来自C ++ 03或C ++ 11,并且使用的版本可以使这些部分正常运行).如果以后要使用GCC 8和-std=c++17编译第四个对象G,则您将需要使用相同版本(或不链接到F)重新编译F,因为F和G中的C ++ 17符号不兼容

This is because C++03 support is stable in all three compiler versions used, and so the C++03 components are compatible between all the objects. C++11 support is stable since GCC 5, but object D doesn't use any C++11 features, and objects E and F both use versions where C++11 support is stable. C++17 support is not stable in any of the used compiler versions, but only object F uses C++17 features and so there is no compatibility issue with the other two objects (the only features they share come from C++03 or C++11, and the versions used make those parts OK). If you later wanted to compile a fourth object, G, using GCC 8 and -std=c++17 then you would need to recompile F with the same version (or not link to F) because the C++17 symbols in F and G are incompatible.

D,E和F之间上述兼容性的唯一警告是,您的程序必须使用GCC 7(或更高版本)中的libstdc++.so共享库.由于对象F是使用GCC 7编译的,因此您需要使用该发行版中的共享库,因为使用GCC 7编译程序的任何部分可能会引入对GCC 4.9或GCC 5中libstdc++.so中不存在的符号的依赖关系.同样,如果链接到使用GCC 8构建的对象G,则需要使用GCC 8中的libstdc++.so以确保找到G所需的所有符号.简单的规则是确保程序在运行时使用的共享库至少与用于编译任何对象的版本一样新.

The only caveat for the compatibility described above between D, E and F is that your program must use the libstdc++.so shared library from GCC 7 (or later). Because object F was compiled with GCC 7, you need to use the shared library from that release, because compiling any part of the program with GCC 7 might introduce dependencies on symbols that are not present in the libstdc++.so from GCC 4.9 or GCC 5. Similarly, if you linked to object G, built with GCC 8, you would need to use the libstdc++.so from GCC 8 to ensure all symbols needed by G are found. The simple rule is to ensure the shared library the program uses at run-time is at least as new as the version used to compile any of the objects.

关于GCC的另一个警告,在您的问题的注释中已经提到,由于GCC 5,libstdc ++中提供了 std::string 的两个实现.这两种实现方式不是链接兼容的(它们具有不同的名称,因此无法链接在一起),但可以共存于同一二进制文件中(它们具有不同的名称,因此,如果一个对象使用,其他使用std::__cxx11::string).如果您的对象使用std::string,则通常应使用相同的字符串实现来编译所有对象.使用-D_GLIBCXX_USE_CXX11_ABI=0进行编译以选择原始的gcc4-compatible实现,或者使用-D_GLIBCXX_USE_CXX11_ABI=1进行选择以选择新的cxx11实现(不要被名称所迷惑,它也可以在C ++ 03中使用,它称为cxx11,因为它符合C ++ 11要求).默认的实现方式取决于GCC的配置方式,但是始终可以在编译时使用宏覆盖默认设置.

Another caveat when using GCC, already mentioned in the comments on your question, is that since GCC 5 there are two implementations of std::string available in libstdc++. The two implementations are not link-compatible (they have different mangled names, so can't be linked together) but can co-exist in the same binary (they have different mangled names, so don't conflict if one object uses std::string and the other uses std::__cxx11::string). If your objects use std::string then usually they should all be compiled with the same string implementation. Compile with -D_GLIBCXX_USE_CXX11_ABI=0 to select the original gcc4-compatible implementation, or -D_GLIBCXX_USE_CXX11_ABI=1 to select the new cxx11 implementation (don't be fooled by the name, it can be used in C++03 too, it's called cxx11 because it conforms to the C++11 requirements). Which implementation is the default depends on how GCC was configured, but the default can always be overridden at compile-time with the macro.

这篇关于链接C ++ 17,C ++ 14和C ++ 11对象是否安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆