-->

是否性病::向量满足Boost.Interprocess中的分配器容器的需求?(Does std::

2019-08-17 10:09发布

In boost::interprocess documentation it is said as requirement for containers to be stored in shared memory:

  1. STL containers may not assume that memory allocated with an allocator can be deallocated with other allocators of the same type. All allocators objects must compare equal only if memory allocated with one object can be deallocated with the other one, and this can only tested with operator==() at run-time.
  2. Containers' internal pointers should be of the type allocator::pointer and containers may not assume allocator::pointer is a raw pointer.
  3. All objects must be constructed-destroyed via allocator::construct and allocator::destroy functions.

I am using gcc 4.7.1 with -std=c++11 (and boost 1.53). Is it safe to use the below defined ShmVector type?

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

I tried a dummy process which uses this type, and it looks it is working, but I am still not sure that the vector in gcc4.7.1 does satisfy all the requirements. I am especially not sure about the first requirement.

#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;

    }
}

Answer 1:

在C ++ 11条分配规则已经略有改变,但我不认为这会影响你的问题。

你可能想知道的第一件事标准说一下吧。 但你真的想检查特定的STL实现是否符合标准,并且不包含错误。

对于第二部分,我强烈推荐去的来源,只是检查,它并不难其实。

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

  • 创建自定义分配器:
    • 使用一些自定义类型为指针,常量指针;
    • construct() destruct()的调用的计数数量;
  • 创建YourCustomType与这也算建筑/残害的人数分配使用。
  • 现在,创建std::vetor<YourCustomType, YourCustomAllocator<YourCustomType>>例如,插入一些元素,清除载体,摧毁它,看看:
    • construct() destruct()调用等于结构的破坏力数YourCustomType
    • typeid(YourCustomAllocator::pointer) == typeid(std::vetor<YourCustomType, YourCustomAllocator<YourCustomType>>::pointer)

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

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

1有没有办法(正确实施)载体将接受一个allocator无章可循。 它会使用您提供力所能及的分配,并且将使用它的一切。 至于==操作符,它在提升的分配来实现,因此它的升压转换器的问题,使运营商==工作,因为它们需要。 虽然我没能找到的确认标准 。

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

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

虽然同一个标准说,这对分配器 :在本国际标准中所描述的容器的实现被允许假设它们的分配器模板参数满足超出表6中的以下两个附加要求。

一个给定的分配器类型的--all实例需要是可互换的并且总是比较彼此相等。

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

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

3只需检查std::vector<T>::clear()方法实现,以查看是否分配器::破坏被调用。 检查std::vector<T>::resize()方法的实现,以查看是否使用分配器::构建体。 我没能找到调用破坏和建设的要求标准 。



Answer 2:

我认为答案是否定的。 因为在实践中(在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>> )。



Answer 3:

我没有信誉发表评论,所以我来回答..如果两个分配器比较平等的,他们是可以互换的。 该比较不等5相同的类型,例如分配器,具有不同的(共享的)存储器初始化。 见分配器 :

a1 == a2 => returns true only if the storage allocated by the allocator a1 can be deallocated through a2. Establishes reflexive, symmetric, and transitive relationship. Does not throw exceptions.

所以,如果你ShmVector实例与创建ShmemAllocator S的比较平等的,你必须是安全的。



文章来源: Does std::vector satisfy the container requirements for Boost.Interprocess allocators?