2013-03-08 43 views
8

boost::interprocess文档据说作为容器要求被存储在共享存储器:std :: vector是否满足Boost.Interprocess分配器的容器需求?

  1. STL容器可以不承担与分配器分配该存储器可以与相同类型的其他分配器被释放。所有分配器对象只有在分配一个对象的内存可以与另一个对象分配时才必须相等,并且这只能在运行时通过operator==()进行测试。
  2. 容器的内部指针应该是allocator::pointer的类型,并且容器可能不承担allocator::pointer是一个原始指针。
  3. 所有物体必须通过allocator::constructallocator::destroy函数构造销毁。

我正在使用gcc 4.7.1和-std = C++ 11(和boost 1.53)。 使用以下定义的ShmVector类型安全吗?

typedef boost::interprocess::allocator<int, 
    boost::interprocess::managed_shared_memory::segment_manager> ShmemAllocator; 
typedef std::vector<int, ShmemAllocator> ShmVector; 

我尝试使用这种类型的虚拟过程,它看起来它是工作,但我现在还不能确定,在gcc4.7.1矢量并满足所有的要求。我特别不确定第一个要求。

#include <iostream> 
#include <boost/interprocess/allocators/allocator.hpp> 
#include <boost/interprocess/managed_shared_memory.hpp> 
#include <vector> 
#include <cstdlib> //std::system 

typedef boost::interprocess::allocator<int, 
     boost::interprocess::managed_shared_memory::segment_manager> ShmemAllocator; 
typedef std::vector<int, ShmemAllocator> ShmVector; 

int main(int argc, char *argv[]) 
{ 
    if(argc == 1){ //Parent process 

     struct shm_remove 
     { 
      shm_remove() { boost::interprocess::shared_memory_object::remove("MySharedMemory"); } 
      ~shm_remove(){ boost::interprocess::shared_memory_object::remove("MySharedMemory"); } 
     } remover; 

     //Create a new segment with given name and size 
     boost::interprocess::managed_shared_memory segment(boost::interprocess::create_only, 
       "MySharedMemory", 65536); 

     //Initialize shared memory STL-compatible allocator 
     const ShmemAllocator allocator(segment.get_segment_manager()); 

     ShmVector* v = segment.construct<ShmVector>("ShmVector")(allocator); 
     v->push_back(1); v->push_back(2); v->push_back(3); 

     //Launch child process 
     std::string s(argv[0]); s += " child "; 
     if(0 != std::system(s.c_str())) 
      return 1; 

    } else { // Child process 

     //Open the managed segment 
     boost::interprocess::managed_shared_memory segment(
       boost::interprocess::open_only, "MySharedMemory"); 

     //Find the vector using the c-string name 
     ShmVector *v = segment.find<ShmVector>("ShmVector").first; 

     for (const auto& i : *v) { 
      std::cout << i << " "; 
     } 
     std::cout << std::endl; 

    } 
} 
+1

根据标准,应该没问题。 – Xeo 2013-03-08 16:01:25

+0

@Xeo我不太确定。该标准指出,STL实现可以自由地假定相同类型的分配器可以释放内存;大多数实现并不依赖于此,但应该检查'std'库的文档。但是,考虑到'g ++'和'libstdC++'的流行,如果Boost没有明确提醒您不兼容,我会感到惊讶。 – 2013-03-08 16:19:16

+0

@Xeo我在标准中发现,子弹3对于所有std :: containers都是正确的:23.2.1.3。但是找不到子弹1和2的任何东西。 – 2013-03-08 16:50:37

回答

0

在C++ 11中,分配器规则稍有改变,但我不认为它会影响你的问题。

您可能首先想知道标准对此有何评论。但是你实际上想要检查你的特定STL实现是否符合标准并且不包含错误。

对于第二部分,我强烈建议去查看源代码,然后检查一下,实际上并不难。

此外,你可以写你的测试,看看它的实际工作正常:

  • 创建自定义分配器:
    • 使用一些自定义类型的指针,常量指针;
    • construct(),destruct()计数呼叫次数;
  • 创建YourCustomType与分配器一起使用,该分配器还计算构造/破坏的数量。
  • 现在,创建std::vetor<YourCustomType, YourCustomAllocator<YourCustomType>>例如,插入一些元素,清除载体,摧毁它,看看:
    • construct()destruct()电话号码等于YourCustomType结构残害的人数。
    • typeid(YourCustomAllocator::pointer) == typeid(std::vetor<YourCustomType, YourCustomAllocator<YourCustomType>>::pointer)

这就是你如何能确保所有的限制。

至于问题的第一部分,这里是一个old C++ standard(不是C++ 11)。

没有办法(正确实施)向量将分配器从无处。它会使用你提供的任何分配器,并将其用于一切。至于operator ==,它是在boost的分配器中实现的,因此它使得operator ==按需要工作是增加的问题。虽然我无法在standard中找到确认。

除非有bug,std::vector<T, YourAllocator>::pointer应该是分配器的指针。 cppreference.com says that,标准says that,(寻找“模板类矢量”):

typedef typename Allocator::pointer    pointer; 
    typedef typename Allocator::const_pointer   const_pointer; 

虽然同样的标准说,这大约allocators:本标准 描述容器 实现允许承担自己的分配器模板参数满足 除表6以外的以下两个附加要求。

- 给定分配器类型的所有实例都必须是可更改的,并且始终相互相等。

--The的typedef成员指针,const_pointer,SIZE_TYPE和differ- ence_type需要是分别T *,T *常量,为size_t,和ptrdiff_t的, 。

所以,实际上标准不允许使用任何指针类型,但我的猜测是实际的STL实现将起作用。

只需检查std::vector<T>::clear()方法实现以查看是否调用allocator :: destroy。检查std::vector<T>::resize()方法的实现以查看是否使用allocator :: construct。我无法找到在the standard中调用销毁和构造的要求。

0

我认为答案是否定的。因为在实践中(在C++ 98中)和在理论上(C++ 11标准),std::vector指针不能是T*以外的东西。

这就是为什么boost::interprocess::vector<T>使用boost::container::vector<T, boost::interprocess::allocator<T>>(而不是std::vector<T, boost::interprocess::allocator<T>>)。

相关问题