我正在尝试将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_;
}
答案 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),文档提供了大量示例。