1

面临的问题:使用文件映射共享的列表不提供列表内的任何数据...

我有一个进程 1,在其中我将所有数据存储为 hash_map 列表,然后我尝试使用文件映射来共享它......在 Process2 中,当我尝试检索列表中的数据时,在列表中找不到数据..

PS:我的exe与dll捆绑在一起,我将我的dll作为process1和exe作为process2 ...

这是我的代码,

过程1

/* 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 
}

过程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;
}
4

2 回答 2

0

首先,常规std::list是一个多级数据结构,它包含对地址空间中其他位置的引用。实际的列表元素不存储在std::list对象内。它们存储在内存中的其他位置。并且std::list只是通过指针来引用这些元素。您的文件映射只是共享顶级std::list对象,但它甚至不尝试共享实际的列表元素。

其次,即使您以某种方式设法神奇地确定并共享了与您相关的所有内容的地址空间的整个区域,std::list它仍然无法工作,除非您以某种方式确保在所有进程中内存都映射到地址空间中完全相同的区域. 这适用于任何使用指针的数据结构。

换句话说,它做不到。您不能只获取现有的平原std::list并通过内存映射共享它。

实际上,您尝试std::list使用此类函数复制非平凡对象(如 )CopyMemory可能已经足以破坏对象的完整性。无需涉及内存映射。

于 2017-04-03T04:57:28.443 回答
0

那是你可以改变的。标准库模板是:

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

因此,您可以根据需要提供自己的内存分配器,作为第二个模板参数。如果您使用默认的,基本上是new,它将在堆外分配节点,这不会在共享内存中。(这似乎是您使用内存映射文件的方式。)另一个进程将能够读取每个列表的头部,但不能读取分配在任何地方的其余节点。

但是,您可以改为在共享内存中分配一个节点池并编写您自己的分配器来分发该共享内存的块,直到它消失为止。(如果每个共享内存块都是可重用的,那么共享内存可以是它自己的小堆。但是,如果您可以在完成所有列表后同时删除它们,那么取消映射就足够了共享内存块。)

或者您可以编写自己的列表类,该列表类使用共享内存中的节点池中的索引,而不是指针,这是一种存储在文件中实际上可能有意义的布局。或者您可以std::array在共享内存中静态分配一个。它的所有存储都在类对象本身内部,并且它的大小是固定的,因此它不会在共享块之外分配任何内存,并且可以开箱即用。

于 2017-04-03T05:01:42.573 回答