Reputation: 131
I've tried to implement a shared memory interface, however I am not able to get it working.
Since it isn't yet working I want to ask help. A shared memory is necessary for my application which is an Multiobjective Evolutionary Algorithm that runs on several processes, however the various processes need to exchange information, and instead of dumping it into a physical file a billion times, I'd rather share memory using this method.
I am on Win7x64 using C++ in VS v120. For the sake of testing, all of this code takes place in the same process until I've figured it out.
My filename is a const string
m_Filename = "Local\\shared_memory"
m_BufferSize = 1024
EDIT 1:
So I see there is some confusion as to what I am trying to do here, well I am confused as well. Looking at the official documentation from MSDN it uses the file mapping with INVALID_HANDLE_VALUE, and they don't seem to create a file on disk. This is fine for my solution. I don't need a file on disk, although either works. The reason I tried to do it the other way is because the first method failed and I started searching, and I came across threads on here where people say that they need to make the actual file as well.
This is a more complete code, and yes I do check the error codes.
The m_Filename is set in the class constructor. Buffer size is constant. I've removed my code which does the physical file stuff, I guess it isn't actually required?
void MemoryMapper::_CreateMappedFile() {
m_Handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
0, m_BufferSize, m_Filename.c_str());
if (m_Handle == NULL)
{
std::cout << m_DebugErrorTitle << "_CreateMappedFile(): " << MM_ERROR_CREATE_FAILED <<
" (" << GetLastError() << ")" << std::endl;
return;
}
m_pBuffer = (LPTSTR)MapViewOfFile(m_Handle, FILE_MAP_ALL_ACCESS, 0, 0, m_BufferSize);
if (m_pBuffer == NULL)
{
std::cout << m_DebugErrorTitle << "_CreateMappedFile(): " << MM_ERROR_MAPPING_FAILED <<
" (" << GetLastError() << ")" << std::endl;
CloseHandle(m_Handle);
return;
}
TCHAR szMsg[] = TEXT("Test message.");
CopyMemory((PVOID)m_pBuffer, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
if (!UnmapViewOfFile(m_pBuffer)) {
std::cout << m_DebugErrorTitle << "_CreateMappedFile(): UnmapViewOfFile() returned false. (" << GetLastError() << ")" << std::endl;
}
if (!CloseHandle(m_Handle)) {
std::cout << m_DebugErrorTitle << "_CreateMappedFile(): CloseHandle() returned false. (" << GetLastError() << ")" << std::endl;
}
if (m_Debug > 1) { std::cout << m_DebugTitle << "Created mapped file: '" << m_Filename << "'." << std::endl; }
}
Running this code and I end up with the console message: [MemoryMapper] Created mapped file: 'Local\shared_memory'.
Then, in the same process, for the sake of testing?? I try to open the file again. This time I get error code 2 saying the file doesn't exist.
bool MemoryMapper::_Open(const std::string& fn) {
if (m_Debug > 2) { std::cout << m_DebugTitle << "Open '" << fn << "'." << std::endl; }
m_OpenHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, fn.c_str());
if (m_OpenHandle == NULL)
{
std::cout << m_DebugErrorTitle << " _Open('" << fn << "'): " << MM_ERROR_OPEN_FAILED << " (" << GetLastError() << ")" << std::endl;
m_IsOpen = false;
return m_IsOpen;
}
m_IsOpen = true;
if (m_Debug > 1) { std::cout << m_DebugTitle << "Open: " << std::to_string(m_IsOpen) << std::endl; }
return m_IsOpen;
}
The filename is the same. 100%.
Why can't I open the file?
Also, should I be checking if a shared memory object exists with the set filename before creating one? Does the object get cleared away when the application terminates?
EDIT 2:
It seems that the handle given from the initial CreateFileMapping() must remain open for the duration I want to use the shared object?
I attempted this and now it seems to work fine. I can make the object, open it, write and close it using separate calls. My mistake was closing the handle upon creation, although, which is correct?
Upvotes: 3
Views: 1561
Reputation: 33706
first of all, if you tried to implement a shared memory interface - for what you create file on disk ? you can do this, but it absolute not need in this case
(3) Now the object in itself should exist in memory, no?
now object really exist in NT-namespace but until you not close last handle to it. when last handle is closed, object name is removed from NT-namespace, unless you not use OBJ_PERMANENT
flag in OBJECT_ATTRIBUTES
. but for this need use NtCreateSection
instead CreateFileMapping
and have SE_CREATE_PERMANENT_PRIVILEGE
if OpenFileMapping
fail with error ERROR_FILE_NOT_FOUND
this mean that name, which you using in call, not exist in NT Namespace. this can be by several reasons: - the process, which call OpenFileMapping
run under another terminal session ( Local\shared_memory
is expanded to \Sessions\<SessionId>\BaseNamedObjects\shared_memory
or to \BaseNamedObjects\shared_memory
if you run it from session 0). you can simply mistake with name.
but faster of all - you close section handle, returned by CreateFileMapping
before you call OpenFileMapping
. because you not use OBJ_PERMANENT
object name deleted when all open handles to them are closed. object itself can continue exist if exist references to it - say when you call MapViewOfFile
- you create reference to section - and it will be not deleted until you not unmap it, but section name will be removed anyway, when all open handles to them are closed.
how i and assume at begin - OpenFileMapping
fail because section no more exist at time which it called. it handles already closed. void MemoryMapper::_CreateMappedFile()
by fact do nothing - this function create temporary object, do some manipulations with it and destroy at exit. all this have no any affect after function return
Upvotes: 1