将void *转换为std :: map

时间:2012-06-20 02:17:59

标签: c++ pointers void-pointers stdmap

我正在尝试将std :: map存储在共享内存段上。但是我无法恢复地图。

我创建共享内存段(使用下面的类)并为其分配映射地址。

但是当我试图恢复它时,我得到一个糟糕的指针。

以下是一些代码段:

    // This is in my header file
    CSharedMem * shMem;
    // This is in my cpp file - inside my class constructor
    shMem = new CSharedMem("MyShMem", 16536);
    void * ptr = shMem->GetAddress();
    std::map<int,int> myMap;
    ptr = &myMap;
    shMem-ReleaseAddress();

    // This is inside another function
    void * ptr = shMem->GetAdress();

    std::map<int,int> myMap = *static_cast<std::map<int,int> *> (ptr);

有没有人有线索?

CSharedMem类 头文件:

    #pragma once

    #include <string>

    class CSharedMem
    {
    public:
    CSharedMem(const std::string& name, std::size_t size);
    ~CSharedMem();

    void* GetAddress() const;
    void ReleaseAddress();
    bool IsShared() const;
    private:
    bool shared_;
    void* address_;

    private:
    void* shm_;
    void* mtx_;
    };

cpp文件:

    #include "StdAfx.h"
    #include "SharedMem.h"
    #include <windows.h>
    CSharedMem::CSharedMem(const std::string& name, std::size_t size)
    : shared_(false), 
    address_(NULL)
    {
    shm_ = CreateFileMapping(INVALID_HANDLE_VALUE, 
                            NULL, PAGE_READWRITE, 
                            0, 
                            static_cast<DWORD>(size), 
                            name.c_str() );
    if( shm_ == INVALID_HANDLE_VALUE )
            throw std::exception("Failed to allocate shared memory.");

    if( GetLastError() == ERROR_ALREADY_EXISTS )
            shared_ = true;

    address_ = MapViewOfFile(shm_, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
    if( address_ == NULL )
            throw std::exception("Failed to map shared memory.");

    if( !shared_ )
            std::memset(address_, 0, size);

    mtx_ = CreateMutex(NULL, FALSE, (name + "MTX").c_str());
    if( mtx_ == INVALID_HANDLE_VALUE )
            throw std::exception("Failed to create shared mutex.");
    }

    CSharedMem::~CSharedMem()
    {
    UnmapViewOfFile(address_);
    CloseHandle(mtx_);
    }
    void* CSharedMem::GetAddress() const
    {
    if(WaitForSingleObject(mtx_, INFINITE) != WAIT_OBJECT_0)
            throw std::exception("Failed to obtain access to shared memory.");

    return address_;
    }

    void CSharedMem::ReleaseAddress()
    {
            ReleaseMutex(mtx_);
    }

    bool CSharedMem::IsShared() const
    {
            return shared_;
    }

2 个答案:

答案 0 :(得分:4)

这个逻辑可能有些可疑:

void * ptr = shMem->GetAddress();
std::map<int,int> myMap;
ptr = &myMap;
shMem->ReleaseAddress();

请注意,您获取了shMem->GetAddress()的地址,但随后声明了局部变量myMap,然后为ptr分配了局部变量的地址。这意味着您实际上不会再ptr指向该共享内存。

我不确定解决这个问题是什么,因为我不确定我在这里看到你想要做什么。如果您打算投射共享内存,您必须成为指向地图的指针,也许您的意思是:

void * ptr = shMem->GetAddress();

/* Construct a map at the given address using placement new. */
new (ptr) std::map<int, int>();
shMem-ReleaseAddress();

稍后,您可以检索地图:

void* ptr = shMem->GetAdress();

/* Note the use of a reference here so we don't just make a copy. */
std::map<int,int> myMap& = *static_cast<std::map<int,int> *> (ptr);

那就是说,我非常怀疑这是否有效,因为map内部分配的指针对于创建它们的进程是本地的,而不是共享的。您可能需要使用分配器做一些有趣的事情才能使其正常工作。

希望这有帮助!

答案 1 :(得分:4)

根据上面的评论,这并不像听起来那么简单。如果跨进程使用共享内存,则无法传递STL容器。

但是,您可以使用boost::interprocess库中的容器。该库专门提供可在共享内存段中使用的容器(vector,deque,set,map),文档提供了大量示例。