【问题标题】:Cast void* to std::map将 void* 转换为 std::map
【发布时间】:2012-06-20 02:17:58
【问题描述】:

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

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

但是当我尝试恢复它时,我得到了一个错误的指针。

这里有一些代码sn-ps:

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

【问题讨论】:

  • 您的代码不可能工作。问题比看起来更复杂。阅读 STL 分配器和新放置。你需要这两个概念。您还必须在固定地址分配共享内存段。

标签: c++ pointers void-pointers stdmap


【解决方案1】:

这个逻辑有点可疑:

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

请注意,您使用shMem-&gt;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 内部分配的指针对于创建它们的进程来说是本地的,而不是共享的。您可能需要对分配器进行一些花哨的操作才能使其正常工作。

希望这会有所帮助!

【讨论】:

  • 我认为你是对的。我可以在早上上班时测试它(距离这里 9 小时)。谢谢你的提示!等我测试了再回复。
  • @templatetypedef +1 用于注意 & 用于不制作副本。很好的答案
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-11
    • 1970-01-01
    • 2017-07-08
    • 2011-03-05
    • 2018-11-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多