【问题标题】:Boost pool allocators won't compile with std::allocate_shared in g++Boost 池分配器不会在 g++ 中使用 std::allocate_shared 进行编译
【发布时间】:2014-12-11 08:11:42
【问题描述】:

编辑:

澄清我想要的结果,因为我没有很好地传达它:
为了能够使用std::allocate_sharedboost::fast_pool_allocator 作为分配方法,使用g++ 4.8 或更高版本和boost 1.56.0。目前这适用于 g++ 4.6,但在 4.7、4.8 和 4.9 上失败。

明确地说,我不希望为 g++4.7 提供这项工作。

测试代码产生错误:

#include "boost/pool/pool.hpp"
#include "boost/pool/pool_alloc.hpp"

#include <memory>

int main(int argc, char** argv)
{
  auto fails = std::allocate_shared<int>( boost::fast_pool_allocator<int>() );

  auto works = std::allocate_shared<int>(boost::fast_pool_allocator<int>(), 5);
}

在我们的代码库中,我们将 std::allocate_shared 与提升池分配器结合使用,这会导致一些令人讨厌的编译错误。然而,这已经在不同版本的 g++ 中发生了变化:
详细信息:64 位,(4.7,4.8) -std=c++11,(4.6) -std=c++0x,boost 1.56.0
4.6 - 编译愉快
4.7 - 使编译器崩溃

内部编译器错误:重新输入错误报告例程。请 提交完整的错误报告,并在适当的情况下提供预处理的源代码。看 获取说明。 预处理后的源码存放在 /tmp/cca0Emq9.out 文件中,请附上 这是你的错误报告。

4.8 - 严重的编译错误

/XXXXXXXXXX/boost/boost/pool/pool_alloc.hpp:399:

错误:使用已删除的函数'std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2u>::_Sp_counted_ptr_inplace(const std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2u>&)’ { 新 (ptr) T(t); } ^

/usr/include/c++/4.8/bits/shared_ptr_base.h:198:错误: 'std::_Sp_counted_base<_lp>::_Sp_counted_base(const std::_Sp_counted_base<_lp>&) [with __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]’ 是私有的 _Sp_counted_base(_Sp_counted_base const&) = 删除; ^ /usr/include/c++/4.8/bits/shared_ptr_base.h:379:错误:在这个 语境 _Sp_counted_ptr_inplace 类最终:公共 _Sp_counted_base<_lp> ^

/usr/include/c++/4.8/bits/shared_ptr_base.h:379:错误:使用已删除 函数‘std::_Sp_counted_base<_lp>::_Sp_counted_base(const std::_Sp_counted_base<_lp>&) [with __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]'

/usr/include/c++/4.8/bits/shared_ptr_base.h:198:错误:在此声明 _Sp_counted_base(_Sp_counted_base const&) = 删除; ^

4.9 - 严重的编译错误(略有不同)

/XXXXXXXXXXX/boost/boost/pool/pool_alloc.hpp:399:错误:使用 删除函数‘std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2u>::_Sp_counted_ptr_inplace(const std::_Sp_counted_ptr_inplace, (__gnu_cxx::_Lock_policy)2u>&)’ { 新 (ptr) T(t); } ^

/usr/include/c++/4.9/bits/shared_ptr_base.h:203:错误: 'std::_Sp_counted_base<_lp>::_Sp_counted_base(const std::_Sp_counted_base<_lp>&) [with __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]’ 是私有的 _Sp_counted_base(_Sp_counted_base const&) = 删除; ^

/usr/include/c++/4.9/bits/shared_ptr_base.h:494:错误:在此 语境 _Sp_counted_ptr_inplace 类最终:公共 _Sp_counted_base<_lp> ^

/usr/include/c++/4.9/bits/shared_ptr_base.h:494:错误:使用已删除 函数‘std::_Sp_counted_base<_lp>::_Sp_counted_base(const std::_Sp_counted_base<_lp>&) [with __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]’

我花了很多钱 时间试图深入了解这一点,我会提供一些帮助 如果有人更熟悉内部工作原理,将不胜感激 这些组件。

【问题讨论】:

  • 内部编译器错误是总是向供应商报告的错误,所以对此无能为力。
  • 我有一种预感,这与其说是编译器的变化,不如说是标准库的变化。
  • 正如@Sehe 所建议的,这是标准库实现而不是编译器的问题。我已经在 (GCC) 5.0.0 20141022 (experimental) 中尝试过了,它可以编译。
  • 我必须承认我很困惑你甚至在一个明显与编译器错误有关的问题上悬赏。如果您想询问解决方法,您可以相应地编辑问题吗?
  • 在 g++ 4.8.3 auto fails = std::allocate_shared&lt;int&gt;( std::allocator&lt;int&gt;()); 上不会失败,因此 boost 必须使用 4.7 中尚未实现的东西。

标签: c++ c++11 boost compiler-errors g++


【解决方案1】:

我花了很多时间查看不同的编译器版本,假设这是 g++4.7 中的崩溃和其他回答者/评论者的 cmets 所暗示的编译器错误。然而,在回到编译错误并研究了一段时间之后,我终于设法以某种程度的特异性理解了编译错误的原因。

所以问题确实出在boost::fast_pool_allocatorboost::pool_allocator 中,回想起来似乎有点明显。问题的基本症结在于 boost allocators construct method 是根据 c++98 标准分配器规范实现的,并且具有一个构造方法,该构造方法采用单个 const& 参数,该参数用于复制构造一个放置新的对象。 c++11 风格使用可变参数模板,并且 args 被传递给通过放置 new 创建的对象的构造函数。在我的测试代码的特定情况下,它是没有将初始化值传递给std::allocate_shared 的变体导致错误。手头的核心问题是 c++11 std::allocate_shared 试图将可变数量的参数传递给只需要一个的 construct() 方法。在我的测试中,我可以在只传入一个值并且不会为其他变体调用它时对构造方法进行断点。例如,如果您正在分配 std::pair&lt;&gt;(2 个参数),则根本不调用构造方法,并且必须使用其他一些机制。我对此进行了一段时间的跟踪,看起来std::allocate_shared 在内部包装了构造调用,如果对构造的调用不匹配,则调用替代方法(通过隐式函数查找)直接构造对象。下面最上面的方法调用分配器的construct()方法,下面的new直接是对象:

alloc_traits.h:250-61

template<typename _Tp, typename... _Args>
static typename
    enable_if<__construct_helper<_Tp, _Args...>::value, void>::type
    _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
{ __a.construct(__p, std::forward<_Args>(__args)...); }

template<typename _Tp, typename... _Args>
static typename
enable_if<__and_<__not_<__construct_helper<_Tp, _Args...>>,
         is_constructible<_Tp, _Args...>>::value, void>::type
    _S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
{ ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); }

这是我有时间真正确定编译错误的来源,但这足以让我找到一个简单有效的问题解决方案。

这里的解决方案很简单; boost 需要更新以使用新的 c++11 分配器规范。这样做实际上非常简单;在 pool_alloc.hpp 中替换所有实例:

void construct(const pointer ptr, const value_type & t)
{ new (ptr) T(t); }

template <typename... Args>
void construct(const pointer ptr, Args&&... args)
{
  new (ptr) T( std::forward<Args>(args)... );
}

这似乎是一个错误,boost 没有更新他们的代码以支持 c++11,但 g++5.0(我确认)编译没有问题的事实意味着添加这种支持不是强制性的。可能是std::allocate_shared 旨在向后兼容旧的分配器接口,并且 4.7、4.8 和 4.9 上的崩溃和编译错误是支持被破坏。我将在 boost bug 跟踪器上发布一张票,看看他们认为这笔交易是什么:boost trac ticket

【讨论】:

    【解决方案2】:

    由于这似乎是 libstdc++ 的一个问题(?),您可以使用标准库函数的 boost 等效函数来代替 boost::allocate_shared。包括&lt;boost/make_shared.hpp&gt;。这是一个 Coliru demo,显示了可以正常编译的四个不同的 GCC 版本。正如我在 cmets 中提到的,std::allocate_shared 与 GCC 的主干构建和 libc++ 一起使用。我找不到与此问题相关的现有错误报告,但您可以为GCCBoost 提交一份报告。

    【讨论】:

    • 嗨,我已经看过boost::allocate_shared,问题是我需要std::shared_ptr,而不是它们的boost等价物。我的问题的标题有些误导,所以我会澄清一下;我需要能够将std::allocate_shared 与指定为分配方法的提升池分配器一起使用。
    猜你喜欢
    • 1970-01-01
    • 2020-10-29
    • 1970-01-01
    • 2012-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    相关资源
    最近更新 更多