将 void* 强制转换为 std::map

Cast void* to std::map

本文关键字:std 转换 map void      更新时间:2023-10-16

我正在尝试在共享内存段上存储一个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);

有人知道吗?

C类头文件:

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

这个逻辑有些可疑:

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内部将是创建它们的过程的本地指针,而不是共享的。 您可能需要对分配器做一些花哨的事情才能使其正常工作。

希望这有帮助!

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

但是,您可以使用boost::interprocess库中的容器。 该库专门提供了可以在共享内存段中使用的容器(向量、双端、集合、映射),文档提供了大量示例。