c++ - Boost 池分配器不会在 g++ 中使用 std::allocate_shared 进行编译

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

编辑:

澄清我想要的结果,因为我没有很好地传达它:
能够将 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 与 boost 池分配器结合使用,这会导致一些严重的编译错误。然而,这已经在不同版本的 g++ 中发生了变化和变化:
详细信息:64 位,(4.7,4.8) -std=c++11,(4.6) -std=c++0x,boost 1.56.0
4.6 - 愉快地编译
4.7 - 编译器崩溃

Internal compiler error: Error reporting routines re-entered. Please submit a full bug report, with preprocessed source if appropriate. See for instructions. Preprocessed source stored into /tmp/cca0Emq9.out file, please attach this to your bugreport.

4.8 - 讨厌的编译错误

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

error: use of deleted function ‘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>&)’ { new (ptr) T(t); } ^

/usr/include/c++/4.8/bits/shared_ptr_base.h:198: error: ‘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]’ is private _Sp_counted_base(_Sp_counted_base const&) = delete; ^ /usr/include/c++/4.8/bits/shared_ptr_base.h:379: error: within this context class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp> ^

/usr/include/c++/4.8/bits/shared_ptr_base.h:379: error: use of deleted function ‘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: error: declared here _Sp_counted_base(_Sp_counted_base const&) = delete; ^

4.9 - 讨厌的编译错误(略有不同)

/XXXXXXXXXXX/boost/boost/pool/pool_alloc.hpp:399: error: use of deleted function ‘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>&)’ { new (ptr) T(t); } ^

/usr/include/c++/4.9/bits/shared_ptr_base.h:203: error: ‘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]’ is private _Sp_counted_base(_Sp_counted_base const&) = delete; ^

/usr/include/c++/4.9/bits/shared_ptr_base.h:494: error: within this context class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp> ^

/usr/include/c++/4.9/bits/shared_ptr_base.h:494: error: use of deleted function ‘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]’

我花了很多钱 是时候弄清楚这个了,我会提供一些帮助 如果有人更熟悉的内部运作,将不胜感激 这些组件。

最佳答案

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

所以问题确实出在boost::fast_pool_allocatorboost::pool_allocator回想起来似乎有点明显。问题的基本症结在于 boost allocators construct method是根据 c++98 标准分配器规范实现的,并且有一个构造方法,该方法采用单个 const& 参数,用于在新位置复制构造对象。 c++11 风格使用可变参数模板,args 被传递给通过 placement new 创建的对象的构造函数。在我的测试代码的特定情况下,它是没有将初始化值传递给 std::allocate_shared 的变体。导致错误。手头的核心问题是 c++11 std::allocate_shared正试图将可变数量的参数传递给 construct()只需要一个的方法。在我的测试中,当只有一个值传入并且其他变体没有调用它时,我可以断点构造方法。例如,如果您正在分配 std::pair<> (2 params) 那么根本不调用构造方法,必须使用其他一些机制。我追踪了一下,它看起来像 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旨在与旧的分配器接口(interface)向后兼容,4.7、4.8 和 4.9 上的崩溃和编译错误是支持被破坏的原因。我会在 boost 错误跟踪器上张贴一张票,看看他们认为这笔交易是什么:boost trac ticket

关于c++ - Boost 池分配器不会在 g++ 中使用 std::allocate_shared 进行编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26396293/

相关文章:

c++ - 当前时间作为创建文件的字符串

c++ - glGenLists(1) 在 OnPaint() 外用 wxThread 返回 0

c++ - 什么存储类是函数内部的静态,为什么?

C++ 使用 Map 中的 Map 检查键是否存在

c++ - strand 和 io 对象(如 tcp::socket)是否需要担心关联 io_service 的生命周期?

c++ - 如何杀死或终止 boost 线程

c++ - gprof 探查器不打印时间摘要

c++ - C++表示回文

c++ - 为什么我无法访问类 'boost::asio::detail::noncopyable' 中声明的私有(private)成员?

c++ - 在 Boost 中实现自旋锁。需要示例