Q:

c++ WINAPI Shared Memory array of structs

I'm trying to share an array of structs through shared named memory using the WINAPI. I'm able to create and manage the shared memory but when trying to share an array of structs the size of the array is always 0 upon reading.
Below is test code i have written which should write/read an array of 10 entries, but even this is failing. My goal is however to write/read a dynamic array of structs containing 2 dynamic arrays and the info they already contain at the moment.
I'm aware i shouldn't share pointers between processes as they could point to a random value. Therefor i'm allocating memory for the arrays using new.
This is what i have so far:
Shared in both processes:
#define MEMSIZE 90024 

typedef struct {
    int id;
    int type;
    int count;
} Entry;

Process 1:
extern HANDLE hMapObject;
extern void* vMapData;

std::vector<Entry> entries;//collection of entries

BOOL DumpEntries(TCHAR* memName) {//Returns true, writing 10 entries
    int size = min(10, entries.size());

    Entry* eArray = new Entry[size];
    for (int i = 0; i < size; i++) {
        eArray[i] = entries.at(i);
    }

    ::hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MEMSIZE, memName);
    if (::hMapObject == NULL) {
        return FALSE;
    }

    ::vMapData = MapViewOfFile(::hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, MEMSIZE);
    if (::vMapData == NULL) {
        CloseHandle(::hMapObject);
        return FALSE;
    }

    CopyMemory(::vMapData, eArray, (size * sizeof(Entry)));
    UnmapViewOfFile(::vMapData);
    //delete[] eArray;
    return TRUE;
}

Process 2:
BOOL ReadEntries(TCHAR* memName, Entry* entries) {//Returns true reading 0 entries
    HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, memName);
    if (hMapFile == NULL) {
        return FALSE;
    }

    Entry* tmpEntries = (Entry*)(MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 10 * sizeof(Entry)));
    if (tmpEntries == NULL) {
        CloseHandle(hMapFile);
        return FALSE;
    }

    entries = new Entry[10];

    for (int i = 0; i < 10; i++) {
        entries[i] = tmpEntries[i];
    }

    UnmapViewOfFile(tmpEntries);
    CloseHandle(hMapFile);
    return TRUE;
}

Writing the 10 entries seems to be working but when trying to read the memory it returns successfully and the size
of the array is 0, like so:
Entry* entries = NULL;
if (ReadEntries(TEXT("Global\Entries"), entries)) {
        int size = _ARRAYSIZE(entries);
        out = "Succesfully read: " + to_string(size);// Is always 0
}

So my question is, what am I doing wrong? I'm sharing the same struct between 2 processes, i'm allocating new memory for the entries to be written to and copying the memory with a size of 10 * sizeof(Entry);. When trying to read I also try to read 10 * sizeof(Entry); bytes and cast the data to a Entry*. Is there something I'm missing? All help is welcome.

A:

I did it some changes to your code:
PROCESS 1:
BOOL DumpEntries(TCHAR* memName)
{
     int size = entries.size() * sizeof(Entry) + sizeof(DWORD);

     ::hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, memName);
     if (::hMapObject == NULL) {
          return FALSE;
     }

     ::vMapData = MapViewOfFile(::hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, size);
     if (::vMapData == NULL) {
          CloseHandle(::hMapObject);
          return FALSE;
     }

     (*(DWORD*)::vMapData) = entries.size();
     Entry* eArray = (Entry*)(((DWORD*)::vMapData) + 1);
     for(int i = entries.size() - 1; i >= 0; i--) eArray[i] = entries.at(i);

     UnmapViewOfFile(::vMapData);
     return TRUE;
}

PROCESS 2:
BOOL ReadEntries(TCHAR* memName, Entry** entries, DWORD &number_of_entries) {
     HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, memName);
     if (hMapFile == NULL) {
          return FALSE;
     }

     DWORD *num_entries = (DWORD*)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
     if (num_entries == NULL) {
          CloseHandle(hMapFile);
          return FALSE;
     }
     number_of_entries = *num_entries;

     if(number_of_entries == 0)
     {
         // special case: when no entries was found in buffer
         *entries = NULL;
         return true;
     }

     Entry* tmpEntries = (Entry*)(num_entries + 1);

     *entries = new Entry[*num_entries];

     for (UINT i = 0; i < *num_entries; i++) {
          (*entries)[i] = tmpEntries[i];
     }

     UnmapViewOfFile(num_entries);
     CloseHandle(hMapFile);

     return TRUE;
}

PROCESS 2 (usage example):
void main()
{
    Entry* entries;
    DWORD number_of_entries;

    if(ReadEntries(TEXT("Global\\Entries", &entries, number_of_entries) && number_of_entries > 0)
    {
        // do something
    }
    delete entries;
}

CHANGES:

I am not using a static size (MEMSIZE) when i map memory, i am calculating exactly memory requiered
I put a "header" to memory mapped, a DWORD for send to process 2 number of entries in buffer
your ReadEntries definition is wrong, i fix it changing Entry* to Entry**

NOTES:

you need to close ::hMapObject handle in process 1 before process 2 calls ReadEntries
you need to delete entries memory returned for ReadEntries in process 2, before you use it
this code works only under same windows user, if you want to communicate a services with user process (for example), you need to handle SECURITY_ATTRIBUTES member in CreateFileMapping procedure

