共享内存上的C ++ STL分配器 - Windows

时间:2017-10-27 10:18:31

标签: c++ memory-management stl shared-memory allocator

在开始之前,我想澄清两件事:

  1. 我不能在这个项目中使用Boost IPC,除了原始的C / C ++库,我不能使用任何东西。

  2. 我看了herehere的答案,仍然无法得到我想要的答案。

  3. 我正在尝试将vector存储在共享内存位置。我已经映射了一个共享内存页面并得到了它的指针。我还使用vector在共享内存上创建了placement new本身,并为其提供了地图视图的LPVOID

    hMapFile = CreateFileMapping(
        INVALID_HANDLE_VALUE,    // use paging file
        NULL,                    // default security
        PAGE_READWRITE,          // read/write access
        0,                       // maximum object size (high-order DWORD)
        BUF_SIZE,                // maximum object size (low-order DWORD)
        szName);                 // name of mapping object
    
    
    if (hMapFile == NULL)
    {
        _tprintf(TEXT("Could not create file mapping object (%d).\n"),
            GetLastError());
        return 1;
    }
    
    pBuf = MapViewOfFile(hMapFile,   // handle to map object
        FILE_MAP_ALL_ACCESS, // read/write permission
        0,
        0,
        BUF_SIZE);
    
    if (pBuf == NULL)
    {
        _tprintf(TEXT("Could not map view of file (%d).\n"),
            GetLastError());
    
        CloseHandle(hMapFile);
    
        return 1;
    }
    
    std::vector<int, shared_allocator<int>>* vec = new(pBuf) std::vector<int, shared_allocator<int>>;
    

    现在,当我尝试从第二个进程访问内存时,我能够抓住vector本身甚至打印其size()。显然,我无法访问任何数据,因为它全部存储在第一个进程的堆中。

    从代码中可以清楚地看到我正在使用我的自定义分配器,如下所示:

    template <class T>
    struct shared_allocator
    {
        typedef T value_type;
        shared_allocator() noexcept {} //default ctor not required by C++ Standard Library    
    
                                                                     // A converting copy constructor:    
        template<class U> shared_allocator(const shared_allocator<U>&) noexcept {}
        template<class U> bool operator==(const shared_allocator<U>&) const noexcept
        {
            return true;
        }
        template<class U> bool operator!=(const shared_allocator<U>&) const noexcept
        {
            return false;
        }
        T* allocate(const size_t n) const;
        void deallocate(T* const p, size_t) const noexcept;
    };
    
    template <class T>
    T* shared_allocator<T>::allocate(const size_t n) const
    {
        if (n == 0)
        {
            return nullptr;
        }
        if (n > static_cast<size_t>(-1) / sizeof(T))
        {
            throw std::bad_array_new_length();
        }
        //void* const pv = malloc(n * sizeof(T));
        //if (!pv) { throw std::bad_alloc(); }
        //return static_cast<T*>(pv);
    
        return (T*) ::operator new(n*sizeof(T));
    }
    
    template<class T>
    void shared_allocator<T>::deallocate(T * const p, size_t) const noexcept
    {
        // free(p);
        delete(p);
    }
    

    此代码是在Microsoft's documentation之后完成的。

    我将mallocfree替换为C ++ newdelete。上面的代码运行良好,第一个进程可以访问所有内容。

    现在我试图修改分配器,以便在共享内存上分配新创建的对象。所以我将allocate函数更改为:

    template <class T>
    T* shared_allocator<T>::allocate(const size_t n) const
    {
        if (n == 0)
        {
            return nullptr;
        }
        if (n > static_cast<size_t>(-1) / sizeof(T))
        {
            throw std::bad_array_new_length();
        }
        //void* const pv = malloc(n * sizeof(T));
        //if (!pv) { throw std::bad_alloc(); }
        //return static_cast<T*>(pv);
    
        cnt += n*sizeof(T);
        void* p = (void*) (static_cast<char*>(pBuf) + cnt);
    
        return (T*) ::operator new(n*sizeof(T), p);
    }
    

    cnt是一个以0开头的全局变量。

    这显然不起作用。它崩溃了一些内存违规异常和所有。我尝试跟踪cnt的更改,第一次增加16,然后增加4。

    每次vector内的_MyFirst()被替换为共享内存中的地址时,vector没有填充正确的数据。

    我知道我做错了,但我已经看过很多地方,似乎无法弄清楚如何做对。如何修改allocator以正确分配共享内存?如果它不能,那么我是否需要重新创建自己的vector

    我一直在关注此article,它表明我只需要编写一个allocator来完成这项工作。

0 个答案:

没有答案