草庐IT

c++ - 混合 libstdc++ 版本

coder 2023-11-16 原文

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

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::whatever 对象并将它们传递给 LibA,后者将它们解释为 GLIBCXX_3.4.13 C++98 风格的对象,这可能不会向前兼容。

这是个问题吗?它会导致应用程序崩溃吗? std::whatever 实现是否在版本之间兼容(相同的内存布局)? C++98 与 C++11 相比如何?

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

  • AFAICT,当 AppB 运行时,只有一个 libstdc++ 被加载,较新的 一。即使 LibA 链接到旧的,它也不会被加载。
  • 但是 libstdc++ 中的符号是有版本控制的。所以,如果 LibA 显式使用 一个符号的旧版本,它将被链接到那个。这表示 AppB 将使用相同功能的 2 个不同实现 和 LibA。
  • std::string 和 containters 是模板类,这意味着 它们的一部分实现最终在它生成的地方结束,一部分 在 libstdc++.so 中。即使加载了较新的 libstdc++,生成的 LibA 中的模板代码来自旧版本。

我想了解在这种情况下到底发生了什么,是否存在风险和无效问题。让团队处于相同的开发环境中不是一种选择。从 API 中删除 std::类也非常困难。

欢迎指点! :)

最佳答案

与 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 中,不同的运行时可能会以不同的方式管理它们的内存(绑定(bind)到不同的 malloc/free)。传递完整的对象或指针时,这可能会导致调用不正确的自由实现。

您可以做些什么来缓解这些问题?

源码分享

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

标准化 libstdc++

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

创建外观

两个团队之间有一个接口(interface),需要说一种共同的语言。这种语言可能应该是 C。

团队 A => C++ 外观/ stub => C 接口(interface) => C++ 外观/代理 => 团队 B。

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

关于c++ - 混合 libstdc++ 版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27881022/

有关c++ - 混合 libstdc++ 版本的更多相关文章

  1. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  4. ruby-on-rails - 在 ruby​​ .gemspec 文件中,如何指定依赖项的多个版本? - 2

    我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这

  5. ruby-on-rails - 如果我将 ruby​​ 版本 2.5.1 与 rails 版本 2.3.18 一起使用会怎样? - 2

    如果我使用ruby​​版本2.5.1和Rails版本2.3.18会怎样?我有基于rails2.3.18和ruby​​1.9.2p320构建的rails应用程序,我只想升级ruby的版本,而不是rails,这可能吗?我必须面对哪些挑战? 最佳答案 GitHub维护apublicfork它有针对旧Rails版本的分支,有各种变化,它们一直在运行。有一段时间,他们在较新的Ruby版本上运行较旧的Rails版本,而不是最初支持的版本,因此您可能会发现一些关于需要向后移植的有用提示。不过,他们现在已经有几年没有使用2.3了,所以充其量只能让更

  6. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

    我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

  7. ruby-on-rails - 如何在发布新的 Ruby 或 Rails 版本时收到通知? - 2

    有人知道在发布新版本的Ruby和Rails时收到电子邮件的方法吗?他们有邮件列表,RubyonRails有一个推特,但我不想听到那些随之而来的喧嚣,我只想知道什么时候发布新版本,尤其是那些有安全修复的版本。 最佳答案 从therailsblog获取提要.http://weblog.rubyonrails.org/feed/atom.xml 关于ruby-on-rails-如何在发布新的Ruby或Rails版本时收到通知?,我们在StackOverflow上找到一个类似的问题:

  8. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  9. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  10. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

随机推荐