【问题标题】:Using concurrently 2 versions of boost同时使用 2 个版本的 boost
【发布时间】:2010-05-25 19:33:37
【问题描述】:

我使用的是 RHEL 5.3,它随 gcc 4.1.2 和 boost 1.33 一起提供。 我想要的一些功能在 boost 1.33 中没有。 因此,想法是升级到新的 boost 版本 1.43。

  1. 是否可以同时使用 boost 1.43 中的一些仅标头库和 1.33 中的其余库?例如我想使用 unorded_map,这是 boost 1.33 中缺少的。

  2. 是否可以同时使用来自不同版本的二进制 boost 库?

【问题讨论】:

    标签: c++ boost


    【解决方案1】:

    不——永远不要这样做!

    这是不可能的,你可能会意外崩溃。

    正确完成它的唯一方法是使用命名空间重命名:即创建替代 boost 版本放置在 不同的 命名空间中。

    最新版本的 BCP 提供了此选项。所以你将使用类似 boost_1_43 的东西来代替 boost。但这对你来说是非常透明的。但你仍然应该知道 其中你不能在同一个 cpp 文件中使用两个版本的 boost。

    也看看这个讨论:Creating Library with backward compatible ABI that uses Boost

    喜欢的脚本重命名命名空间、定义和包含,因此您实际上可以包含两个 类似的 boost 版本

    #include <boost/foo.hpp>
    #include <myboost/bar.hpp>
    
    boost::foo f;
    myboost::bar b;
    

    Boost BCP 不允许这样做。

    但是你仍然应该小心,因为有些库在导出外部“C”符号时没有 boost 前缀,boost::thread 和 boost::regex 的 C API (regexec, regcomp)

    编辑

    作为此类问题的示例,请创建以下文件:

    a.cpp:

    template<typename Foo>
    Foo add(Foo a, Foo b)
    {
            return a+b;
    }
    
    
    int foo(int x,int y)
    {
            return add(x,y);
    }
    

    b.cpp:

    template<typename Foo>
    Foo add(Foo a, Foo b)
    {
            return a-b;
    }
    
    
    int bar(int x,int y)
    {
            return add(x,y);
    }
    

    test.cpp:

    #include <iostream>
    
    int foo(int,int);
    int bar(int,int);
    
    int main()
    {
            std::cout<< foo(10,20) <<" " <<bar(10,20) << std::endl;
    }
    

    编译它们:

    g++ a.cpp b.cpp test.cpp
    

    你会期望:

    30 -10
    

    但你会得到

    30 30
    

    -10 -10
    

    取决于链接顺序。

    所以使用两个 boost 版本你可能会不小心使用来自其他 boost 和 crash 的符号 与此程序中的符号相同 int add&lt;int&gt;(int,int) 甚至被解析为相同的符号 如果放在不同的编译单元中。

    【讨论】:

    • +1 链接 - 尽管我不同意你答案的前半部分。
    • @richj - 在所有链接都是显式的 DLL 平台下是可能的,但是对于 ELF 会发生坏事(根据经验)
    【解决方案2】:

    如果运气好(并且非常小心),您可以可能摆脱使用全新的标题。对于几乎其他任何事情,它可能会很快变得丑陋,因为 Boost 的某些部分引用了其他部分,并且如果某些 v. 1.33 代码意外加载了 v. 1.43 标头作为其依赖项,那么您很有可能会去结果会导致一些问题——你所能期望的最好的结果是在那一点上快速、干净地死机(崩溃),但你可能很容易变得更糟(例如,无声的数据损坏)。

    【讨论】:

      【解决方案3】:

      更新

      我认为我最初的答案对链接器的功能和使用的选项做出了太多假设,而且很可能完全错误。通常我会删除它,但讨论中的某些要点未包含在其他答案中。

      我发现构建一个行为良好的封闭源代码库所需的意义令人惊叹。

      原答案

      只要您在每个编译步骤使用一个版本,那么您应该没问题,因为代码是在编译时生成的,并且生成的符号应该限制在编译步骤的范围内。

      我假设 Boost 仍然是一个没有可链接库的模板库。如果不是,那么只要您不链接多个版本的库,您仍然可以。

      我在这方面可能是错误的,但这意味着您不能使用针对与为您的应用程序定义的版本不同的 Boost 版本构建的任何第三方库。我所阅读或听到的任何内容都没有暗示此限制适用。

      如果您正在构建自己的应用程序,那么我会坚持为您自己的所有代码使用一个版本的 Boost。它不必与 RHEL 提供的版本相同。

      更新

      与Artyom的例子相比,我说的场景更像是这样的:

      g++ -c -I/usr/include/boost_1.31 a.cpp
      g++ -c -I/usr/include/boost_1.39 b.cpp
      ar rcs liba.a a.o
      ar rcs libb.a b.o
      g++ -I/usr/include/boost_1.41 test.cpp liba.a libb.a -o test
      

      ...现在我理解了 Artyom 的观点,因为这取决于链接器是否更喜欢同一个库文件中的符号。

      【讨论】:

      • ELF 是指:en.wikipedia.org/wiki/Executable_and_Linkable_Format?如果是这样,我对此一无所知,但我看不出它与 C++ 元编程有什么关系。请解释一下。
      • @richj 请参阅我的答案中的示例。
      • 谢谢你的例子。我已经更新了我的帖子,以更好地解释我正在谈论的场景。当我的意思是“一起编译的文件集”时,我不应该使用“编译单元”。我将其更改为“编译步骤”。
      • @Artyom 这是否意味着必须在 ELF 平台上从源代码构建所有内容才能构建依赖于 Boost 库的应用程序?或者你能用增量链接或共享库解决多个 Boost 版本的问题吗?
      • 顺便说一句,这不仅仅是 ELF,Windows 上的静态链接具有相同的功能。甚至共享库(ELF)在运行时也会有完全相同的问题。对于 dll,如果没有在 DLL 的 API 中公开,您可以使用两个不同版本的 boost 来拥有两个不同的 dll。所以不要这样做......永远。
      猜你喜欢
      • 2013-04-27
      • 2012-06-19
      • 1970-01-01
      • 1970-01-01
      • 2011-07-17
      • 1970-01-01
      • 2020-09-05
      • 2015-05-04
      • 2017-09-25
      相关资源
      最近更新 更多