1

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;
}
Angelina
  • 13
  • 3

2 Answers2

0

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.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
0

That’s possible for you to change. The standard library template is:

template<class T, class Allocator = std::allocator<T> > class list;

So you can provide your own memory allocator if you want, as the second template parameter. If you use the default one, which is basically new, it would allocate nodes off the heap, which would not be in shared memory. (That appears to be how you’re using the memory-mapped file.) The other process would be able to read the head of each list, but not the rest of the nodes, allocated wherever.

You could instead, however, allocate a pool of nodes in shared memory and write your own allocator that handed out chunks of that shared memory until it was gone. (If each shared-memory block is re-usable, the shared memory could be its own mini-heap. If you can just delete all the lists at the same time when you’re done with them, though, it would suffice to unmap the shared-memory block.)

Or you could write your own list class that used indices into the pool of nodes in shared memory, rather than pointers, which is a layout that it would actually make potential sense to store in a file. Or you could allocate a std::array statically in shared memory. All its storage is inside the class object itself, and it’s fixed size, so it doesn’t allocate any memory outside the shared block and would work out of the box.

Davislor
  • 14,674
  • 2
  • 34
  • 49