I’m trying to store a std::map on a shared memory segment. But I’m not being able to recover the map.
I create the shared memory segment (using the class below) and assign the map address to it.
But when I try to recover it I get a bad pointer.
Here are some code snippets:
// 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);
Does anyone have a clue?
CSharedMem class
Header file:
#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 file:
#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_;
}
Something is fishy with this logic:
Notice that you obtain an address with
shMem->GetAddress(), but then declare a local variablemyMapand then assignptrthe address of the local variable. This means that you won’t actually haveptrpointing at that shared memory any more.I’m not sure what the fix to this is, since I’m not sure I see what you’re trying to do here. If you intended to cast the shared memory you got to be a pointer to a map, perhaps you meant this:
Later on, you can retrieve the map:
That said, I’m extremely doubtful that this will work because the pointers allocated internally inside the
mapwill be local to the process that creates them, not shared. You’d probably need to do something fancy with allocators to get this to work correctly.Hope this helps!