Search code examples
c++file-mapping

In C++, How std::list in a struct will allocate memory and while using this in file mapping, the list result as empty


Problem faced : List shared by using file mapping does'nt provide any data inside the list...

I have a process 1, in which i store all my datas as a List of hash_map and then i try to share that using File mapping ... in Process2 while i try to retrieve the datas inside list, there is no data found inside list..

PS: My exe is bundled with dll, I make my dll as process1 and exe as process2...

Here is my code,

Process1

/* this is in common headerFile */
typedef hash_map <std::wstring,std::wstring> AttrValues;
CString FileName = L"E:\\DataLog.txt";

TCHAR szName[]=TEXT("Local\MyFileMappingObject");

struct ADstruct
{
    std::list<AttrValues> StList;
    int i;
};


/*Sharememory.cpp*/
DWORD SharedMemory()
{ 
                AttrValues HardCode;//Sample data which i am hard coding for testing
                HardCode[L"NAme"] = L"Test";
                HardCode[L"D.Name"] = L"SAP";
                std::list <AttrValues> HardCodedList;
                HardCodedList.push_back(HardCode);

ADstruct CheckStruct;

CheckStruct.i = 10;
        CheckStruct.StList = HardCodedList;

HANDLE hFile = INVALID_HANDLE_VALUE;// HANDLE  hFile;

    hFile = CreateFile(FileName.GetBuffer(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL);

    if(hFile == INVALID_HANDLE_VALUE)
    {
        printf("Error in creating a file..!");
        return 0;
    }
hMapFile = CreateFileMapping(
        hFile, // use paging file
        NULL, // default security
        PAGE_READWRITE, // read/write access
        0, // maximum object size (high-order DWORD)
        sizeof(ADstruct), // maximum object size (low-order DWORD)
        szName); // name of mapping object

    if (hMapFile == NULL)
    {
        _tprintf(TEXT("Could not create file mapping object (%d).\n"),
                                                                     GetLastError());
        return 1;
    }
ADstruct *ADobj = new ADstruct;



ADobj = (ADstruct *) MapViewOfFile(hMapFile, // handle to map object
                                  FILE_MAP_ALL_ACCESS, // read/write permission
                                  0,
                                  0,
                                sizeof(ADstruct) );


    CopyMemory( (ADstruct *) ADobj, &CheckStruct , sizeof(ADstruct) );
UnmapViewOfFile(pBuf);

    CloseHandle(hMapFile); 
return 0 
}

Process 2:

BOOL ReadMemoryMapping()
{
    hash_map<LPWSTR,LPWSTR> ADdata;

   HANDLE hMapFile;

   HANDLE hFile = INVALID_HANDLE_VALUE;
   hMapFile = OpenFileMapping(
                   FILE_MAP_ALL_ACCESS,   // read/write access
                   FALSE,                 // do not inherit the name
                   szName);               // name of mapping object

   if (hMapFile == NULL)
   {
      _tprintf(TEXT("Could not open file mapping object (%d).\n"),
             GetLastError());
      return 1;
   }
ADstruct * readstruct;

    readstruct = (ADstruct *) MapViewOfFile(hMapFile, // handle to map object
               FILE_MAP_ALL_ACCESS,  // read/write permission
               0,
               0,
              sizeof(ADstruct));
    _tprintf(L"\nprint data%d\n",readstruct->i);

    AttrValues At ;
    for(std::list<AttrValues>::iterator list_iter = readstruct->StList.begin(); 
        list_iter != readstruct->StList.end(); list_iter++)
    {
        At.clear();
         At = *list_iter; //*****Here the code crashes as there is no datas inside***
        if(At.empty() == 1)
            printf("List is empty\n");
        std::wcout<<endl<<endl<<"Attribute List In EXE : StList"<<endl;

        for(AttrValues :: iterator it1 = list_iter->begin(); it1!= list_iter->end(); it1++)
        {
            std::wcout<<it1->first<<endl;
            std::wcout<<it1->second<<endl;

        }
    }
 UnmapViewOfFile(readstruct);

   CloseHandle(hMapFile);

   return 0;
}

Solution

  • Firstly, regular std::list is a multi-level data structure, which contains references to other locations in address space. The actual list elements are not stored inside the std::list object. They are stored elsewhere in memory. And std::list simply refers to these elements through pointers. Your file mapping simply shares the top-level std::list object but it does not even attempt to share the actual list elements.

    Secondly, even if you somehow manage to magically determine and share the entire region of address space that holds everyhting related to your std::list it still would not work, unless you somehow ensured that in all processes that memory is mapped to exactly the same region in address space. That applies to any data structure that uses pointers.

    In other words, it can't be done. You can't just take an existing plain std::list and share it through memory mapping.

    In fact, your attempts to copy non-trivial object (like std::list) by using such functions as CopyMemory might be already enough to destroy the object's integrity. No need to involve memory mappings.