我正在尝试使用 WINAPI 通过共享命名内存来共享结构数组。我能够创建和管理共享内存,但是当尝试共享结构数组时,读取时数组的大小始终为 0。
下面是我编写的测试代码,它应该写入/读取 10 个条目的数组,但即使这样也是失败的。然而,我的目标是编写/读取包含 2 个动态数组的动态结构数组以及它们目前已包含的信息。
我知道我不应该在进程之间共享指针,因为它们可能指向随机值。因此,我正在使用 new 为数组分配内存。
这是我目前所拥有的:
在两个进程中共享:
#define MEMSIZE 90024
typedef struct {
int id;
int type;
int count;
} Entry;
过程 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;
}
过程 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;
}
写入 10 个条目似乎有效,但是当尝试读取内存时,它成功返回并且大小 数组的值为 0,如下所示:
Entry* entries = NULL;
if (ReadEntries(TEXT("Global\Entries"), entries)) {
int size = _ARRAYSIZE(entries);
out = "Succesfully read: " + to_string(size);// Is always 0
}
所以我的问题是,我做错了什么?我在 2 个进程之间共享相同的结构,我正在为要写入的条目分配新内存并复制大小为 10 * sizeof(Entry);
的内存。在尝试读取时,我还尝试读取 10 * sizeof(Entry);
字节并将数据转换为 Entry*
。有什么我想念的吗?欢迎所有帮助。
最佳答案
根据粗略的检查,这段代码似乎试图将包含 std::string
的结构映射到共享内存中,以供另一个进程使用。
不幸的是,这场冒险还没开始就注定了。即使您让数组长度正确传递,我也希望另一个进程会立即崩溃,只要它闻到另一个进程试图映射到共享内存段的 std::string
.
std::string
是非常重要的类。 std::string
维护指向保存实际字符串数据的缓冲区的内部指针;缓冲区在堆上分配。
你确实明白 sizeof(std::string)
不会改变,无论字符串包含五个字符,还是《 war 与和平》的全部内容,对吧?停下来想一想,这怎么可能,只需要几个字节就可以存储一个 std::string
?
一旦你想一想,就会清楚为什么将一个进程的 std::string
映射到一个共享内存段,然后试图由另一个进程获取它们是不会工作。
唯一可以实际映射到/从共享内存映射的是plain old data ;尽管在某些情况下您也可以摆脱聚合。
关于c++ WINAPI 共享内存结构数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37890631/