Win32无法从共享内存中获取数据

时间:2017-11-09 21:22:14

标签: c++ shared-memory

我可以创建共享内存对象,也可以使用MSDN的指南打开它。

第一个进程创建它并保持打开状态。 第二个进程输入一个字符串。 然后第一个进程将尝试恢复该字符串并显示它,但我似乎无法得到任何东西。它总是空的,虽然看起来写作部分设置正确。

我在这样的内存中写了一个字符串:

int MemoryMapper::Write(const std::string& data) {

    m_pBuffer = (LPCTSTR)MapViewOfFile(m_OpenHandle, FILE_MAP_ALL_ACCESS, 0, 0, m_BufferSize);

    if (m_pBuffer == NULL)
    {
        std::cerr << m_DebugErrorTitle << "Write(): " << MM_ERROR_MAPPING_FAILED << " {" << GetLastError() << "}" << std::endl;
        Close();
        return 0;
    }

    const char* cdata = _CharFromString(data);
    int size = (lstrlen(cdata) * sizeof(const char*));

    CopyMemory((PVOID)m_pBuffer, cdata, size);
    m_WrittenSize += size;

    if (m_Debug > 1) { std::cout << m_DebugTitle << "Wrote " << size << " bytes." << std::endl; }
    return size;
}

然后我就这样读了:

int MemoryMapper::Read(std::string& data) {

    m_pBuffer = (LPCTSTR) MapViewOfFile(m_OpenHandle, FILE_MAP_ALL_ACCESS, 0, 0, m_BufferSize);

    if (m_pBuffer == NULL)
    {
        std::cerr << m_DebugErrorTitle << "Read(" << m_MemoryName << "): " << MM_ERROR_MAPPING_FAILED << " {" << GetLastError() << "}" << std::endl;
        Close();
        return 0;
    }

    MessageBox(NULL, m_pBuffer, TEXT("TEST MESSAGE"), MB_OK);

    int size = (lstrlen(m_pBuffer) * sizeof(const char*));
    UnmapViewOfFile(m_pBuffer);
    return size;
}

m_pBuffer是LPCTSTR,m_BufferSize是1024。 对象的特定名称在两端都是相同的。我已经确定了创建和打开/关闭部分的工作原理。

第二个进程根据代码写入'8312.000000,8312.000000',总共92个字节。

读者的缓冲区是空的。

我做错了什么? 我尝试了各种数据类型,char,const char,string,tchar - 结果相同。

1 个答案:

答案 0 :(得分:3)

8312.000000,8312.000000的长度为23个字符。

std::string::c_str()返回以null结尾的char*指针。 lstrlen()返回最多但不包括空终止符的字符数。

Write()将字符串长度乘以sizeof(const char*),在32位进程中为4(64位进程中为8)。 Write()超出了data的范围,并尝试将23 * 4 = 92字节复制到m_pBuffercdata保证指向包含24个字节最大值(23个字符+ 1个空终止符)的缓冲区,因此Write()到达周围的内存。那是未定义的行为,而任何都可能发生。在您的情况下,您可能最终将额外的垃圾复制到m_pBufferWrite()可能很容易崩溃。

事实上,如果data的字符数超过256个,Write()会崩溃,因为它会尝试将257+ * 4 > 1024字节复制到m_pBuffer - 超过{{ 1}}映射访问。

你应该将字符串长度乘以MapViewOfFile(),而不是sizeof(std::string::value_type),它总是1(所以你可以省略乘法)。

sizeof(char)具有相同的Read()错误,但它也假设sizeof()在调用m_pBufferlstrlen()时始终为空终止,但MessageBox()并不保证始终存在空终止符。

话虽如此,请尝试更像这样的事情:

Write()