微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C++ 放置新的与 boost 分配器不兼容

如何解决C++ 放置新的与 boost 分配器不兼容

我正在使用 Boost.Interprocess 共享内存,并且我正在将进程间分配器与一些 STL 兼容容器一起使用,当涉及到 placement new 时,代码将无法编译,因为placement new 期望 void *boost::interprocess::allocator::pointer 不能转换为 void *

下面是重现这个的代码


#include <memory>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
namespace ipc = boost::interprocess;

typedef ipc::allocator<int,ipc::managed_shared_memory::segment_manager> ShmemAllocator;

int main() {
    struct shm_remove {
      shm_remove() { ipc::shared_memory_object::remove("MySharedMemory"); }
      ~shm_remove() { ipc::shared_memory_object::remove("MySharedMemory"); }
    } remover;
  ipc::managed_shared_memory segment(ipc::open_or_create,"MySharedMemory",1024 * 1024 * 10);

  ShmemAllocator shm_alloc(segment.get_segment_manager());
  ShmemAllocator::pointer shm_ptr = shm_alloc.allocate(1);

  std::allocator<int> std_alloc;
  std::allocator<int>::pointer std_ptr = std_alloc.allocate(1);
  
  new(std_ptr) int(3);
  new(shm_ptr) int(3); // this line doesn't work

  return 0;
}

我得到的编译错误

/home/ziqi.liu/ClionProjects/shared_memory_experiment/src/main_a.cpp: In function ‘int main()’:
/home/ziqi.liu/ClionProjects/shared_memory_experiment/src/main_a.cpp:22:21: error: no matching function for call to ‘operator new(sizetype,boost::interprocess::allocator<int,boost::interprocess::segment_manager<char,boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family>,boost::interprocess::iset_index> >::pointer&)’
   new(shm_ptr) int(3); // this line doesn't work
                     ^
In file included from /usr/include/c++/5/ext/new_allocator.h:33:0,from /usr/include/x86_64-linux-gnu/c++/5/bits/c++allocator.h:33,from /usr/include/c++/5/bits/allocator.h:46,from /usr/include/c++/5/memory:63,from /home/ziqi.liu/ClionProjects/shared_memory_experiment/src/main_a.cpp:1:
/usr/include/c++/5/new:111:7: note: candidate: void* operator new(std::size_t)
 void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc)
       ^
/usr/include/c++/5/new:111:7: note:   candidate expects 1 argument,2 provided
/usr/include/c++/5/new:119:7: note: candidate: void* operator new(std::size_t,const std::nothrow_t&)
 void* operator new(std::size_t,const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
       ^
/usr/include/c++/5/new:119:7: note:   no kNown conversion for argument 2 from ‘boost::interprocess::allocator<int,boost::interprocess::iset_index> >::pointer {aka boost::interprocess::offset_ptr<int,long int,long unsigned int,0ul>}’ to ‘const std::nothrow_t&’
/usr/include/c++/5/new:129:14: note: candidate: void* operator new(std::size_t,void*)
 inline void* operator new(std::size_t,void* __p) _GLIBCXX_USE_NOEXCEPT
              ^
/usr/include/c++/5/new:129:14: note:   no kNown conversion for argument 2 from ‘boost::interprocess::allocator<int,0ul>}’ to ‘void*’
In file included from /home/ziqi.liu/.tspkg/include/boost/interprocess/mem_algo/detail/mem_algo_common.hpp:35:0,from /home/ziqi.liu/.tspkg/include/boost/interprocess/allocators/detail/allocator_common.hpp:35,from /home/ziqi.liu/.tspkg/include/boost/interprocess/allocators/allocator.hpp:30,from /home/ziqi.liu/ClionProjects/shared_memory_experiment/src/main_a.cpp:2:
/home/ziqi.liu/.tspkg/include/boost/container/detail/placement_new.hpp:24:14: note: candidate: void* operator new(std::size_t,void*,boost_container_new_t)
 inline void *operator new(std::size_t,void *p,boost_container_new_t)
              ^
/home/ziqi.liu/.tspkg/include/boost/container/detail/placement_new.hpp:24:14: note:   candidate expects 3 arguments,2 provided
CMakeFiles/main_a.dir/build.make:62: recipe for target 'CMakeFiles/main_a.dir/src/main_a.cpp.o' Failed
make[2]: *** [CMakeFiles/main_a.dir/src/main_a.cpp.o] Error 1
CMakeFiles/Makefile2:162: recipe for target 'CMakeFiles/main_a.dir/all' Failed
make[1]: *** [CMakeFiles/main_a.dir/all] Error 2
Makefile:83: recipe for target 'all' Failed
make: *** [all] Error 2

我确定一定有办法做到这一点,因为 boost 自己的容器都与 boost::interprocess::allocator::pointer 兼容,但我不确定他们是怎么做到的......我想我应该看看新版位的替代方案?

解决方法

在容器中使用分配器时,构造对象的正确方法是调用

myclass2

请参阅 CppReference 了解更多信息。

如果您需要 C++03 解决方案(C++03 中没有 std::allocator_traits<AllocatorType>::construct(alloc,pointer,...constructor parameters...)),那么您可以直接调用分配器 allocator_traits 方法 - 但这不是推荐的解决方案。

,

你说得对,标准容器不提供花哨的指针。参见例如

我通常会选择使用 Boost Container 集合,因为它们确实支持这些。而且,根据我的经验,它们在作用域分配器适配器上的表现似乎比大多数标准库实现要好得多。

只是为了偷懒:

Live on Coliru

#include <boost/container/container_fwd.hpp>
#include <boost/container/scoped_allocator_fwd.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/container/vector.hpp>
#include <boost/container/map.hpp>
#include <boost/container/string.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <functional>
#include <memory>
namespace ipc = boost::interprocess;
namespace bc = boost::container;

template <typename T>
using Alloc = ipc::allocator<T,ipc::managed_mapped_file::segment_manager>;
template <typename T>
using ScopedAlloc = bc::scoped_allocator_adaptor<Alloc<T> >;

template <typename T>
using SharedVector = bc::vector<T,Alloc<T> >;

template <typename K,typename V,typename Pair = std::pair<K const,V> >
using SharedMap = bc::map<K,V,std::less<>,ScopedAlloc<Pair> >;

int main() {
    ipc::managed_mapped_file segment(ipc::open_or_create,"MySharedMemory",1024 * 100);
    auto* sm = segment.get_segment_manager();

    {
        auto &v = *segment.find_or_construct<SharedVector<int>>("vector")(sm);
        v.push_back(3);
        v.insert(v.begin(),5);
        v.emplace_back(16);
    }

    {
        using String = bc::basic_string<char,std::char_traits<char>,ScopedAlloc<char> >;
        auto &m = *segment.find_or_construct<SharedMap<String,String> >("map")(sm);

        m.emplace("whoa","not bad");
        m.emplace("at","all");
    }
}

请注意,由于 Coliru 的限制,我使用了较小的尺寸和 managed_mapped_file

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?