混合libstdc ++版本

时间:2015-01-10 20:43:28

标签: c++ c++11 gcc

有两个软件团队为同一个操作系统开发C ++应用程序(Scientific Linux 6.5):

Team_A 使用操作系统提供的编译器和库(GCC 4.4.7,GLIBC_2.12,GLIBCXX_3.4.13)来构建其C ++ 98应用程序和各种共享库。

Team_B 使用较新的GCC版本(4.8.3),该版本是从源代码构建的。它是一个本机编译器,它链接到OS libc,并使用OS标准头,但有自己的stdc ++版本(GLIBCXX_3.4.19)。 Team_B在C ++ 11模式下使用此编译器来构建其应用程序( AppB ),并随之部署libstdc ++和libgcc_s。

Team_A以共享库(.so,.hpp)的形式向Team_B提供服务: LibA 。该库的API是一组C ++类(标题中的声明,.so中的实现),并且这些方法将std :: string和其他stdc ++类作为参数。

此时我们遇到问题:AppB构造GLIBCXX_3.4.19 C ++ 11样式std ::无论什么对象并将它们传递给LibA,LibA将它们解释为GLIBCXX_3.4.13 C ++ 98样式对象,这可能不是向前兼容。

这是一个问题吗?它会导致应用程序崩溃吗? std ::的任何实现是否兼容版本(相同的内存布局)?那么c ++ 98和C ++ 11呢?

一些情节曲折使我更加困惑:

  • AFAICT,当AppB运行时,只有一个libstdc ++加载,更新 一。即使LibA与旧版本链接,也不会加载。
  • 但是libstdc ++中的符号是版本化的。所以,如果LibA明确使用了 它的旧版本将与之相关联。这意味着 AppB将使用相同功能的2种不同实现 和LibA。
  • std :: string和containters是模板类,这意味着 它们的一部分实现最终会产生它的一部分 在libstdc ++中。所以。即使加载了较新的libstdc ++,也会生成 LibA中的模板代码来自旧版本。

我想了解在这种情况下究竟发生了什么,如果它有风险,并且无效问题。让团队处于相同的开发环境不是一种选择。从API中删除std :: classes也很难。

欢迎任何指示! :)

1 个答案:

答案 0 :(得分:3)

与C不同,C ++没有定义的ABI。这意味着......

  1. C ++重整可能会更改wikipedia : name mangling。请注意Alpha名称修改如何更改。
  2. 班级的结构可能不同。制定结构的protected:private:public:部分可能会有不同的决定。 vtable的位置和含义可以在编译器之间移动。可能存在不同的预定义函数,例如不同编译器版本之间的vtable中的typeinfo。
  3. STL中的结构实现可能在C ++版本之间有所不同(例如,字符串共享在早期的Visual Studio实现中完成,但在C ++ 11中已被禁止)。
  4. 在Windows中,不同的运行时可能会以不同方式管理其内存(绑定到不同的malloc / free)。传递完整对象或指针时,这可能导致调用不正确的自由实现。
  5. 你可以做些什么来缓解这些问题?

    来源共享

    不是提供已编译的库,而是将服务作为源代码提供,以便在同一环境中进行编译。

    对libstdc ++进行标准化

    源代码构建的编译器,可以使用旧的stdC ++重新构建。这将限制第3点的影响。

    创建一个立面

    两个团队之间有一个界面,需要说一种共同的语言。这种语言可能应该是C.

    A队=> C ++ facade / stub => C接口=> C ++外观/代理=> B队。

    立面应该建在将要使用的环境中。