【问题标题】:How to copy for the following scenario?如何复制以下场景?
【发布时间】:2019-09-19 13:19:19
【问题描述】:

我有一个Memory mapped file 和对应的MapViewOfFile 句柄。 memory mapped file 将包含两部分数据:

  1. unsigned int指定实际数据的长度
  2. 实际相关数据

例如如果我的实际数据长度为10 个字符,则内存映射文件将是:

10
abcdefghij

abcdefghij 是我想要的数据,并且会有一个换行符 b/w 长度数字和数据。如果需要,我也可以随意使用任何其他分隔符。

现在我想先读取unsigned int,以便能够读取实际数据。我正在考虑memcpy,但我不确定如何获得确切的无符号整数值,因为我认为memcpy 一个字符一个字符地复制。如何从内容中提取10

【问题讨论】:

  • 当您说数据以无符号整数开头时,您的意思是 ascii 编码的数字,而不是大端或小端整数值?但是,如果 lenght 后面的数据是以数字开头的,怎么区分呢?
  • @jdehesa 是绝对正确的。如果您可以控制文件,我建议指定“文件的前 x 个字节是数据的长度”或“ascii 编码的数字后跟换行符”。
  • 这个内存映射文件的来源将是另一个程序,它将一个字符串作为字节数组复制到共享内存中
  • 你能保证实际数据不会以数字字符开头吗?
  • 不,我不能保证

标签: c++ visual-c++ shared-memory memcpy


【解决方案1】:

你可以这样做:

#include "windows.h"
#include <iostream>

int main() {
    const size_t buffer_size = 4098;
    const char* name = "my_shared_memory"; //sm name
    HANDLE file = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, buffer_size, name);
    LPVOID region = MapViewOfFile(file, FILE_MAP_ALL_ACCESS, 0, 0, buffer_size);

    const char* const msg = "this is my data"; //this is the string you want to pass
    const int msg_size = strlen(msg) + 1; //this is the size of the string data with \0
    const int total_size = msg_size + sizeof(int); //the total size of your data: the size of the string and the string by itself
    char* const data = (char*)malloc(total_size); //get some memory to place this data
    ((int*)data)[0] = msg_size; //set the first part of the data with the string msg size
    memcpy(data + sizeof(int), msg, msg_size); //set the msg by it self just after the size

    CopyMemory(region, data, total_size); //put on sm

    const int retrieved_size = ((int*)region)[0]; //retrieves the size of the msg from the sm
    char* const retrieved_msg = (char*)malloc(retrieved_size); //alloc some space for receive the msg with the retrieved size
    memcpy(retrieved_msg, (char*)region + sizeof(int), retrieved_size); //set the msg in the previous allocated memory
    std::cout << retrieved_msg << std::endl; //prints the msg

    free(data);
    free(retrieved_msg);
}

在这个question 中,您有一些解决方案来检查字节序。然后,如有必要,您可以再使用一个字节来存储此信息。如果字节序不同,可以swap bytes


乔希评论的解决方案:

对于 ASCII 编码的大小,您可以将它作为字符串保存,而不是将 int 二进制编码的大小存储在内存中:

const int max_digits_size = 3;
char number[max_digits_size + 1];
sprintf(number, "%d", msg_size);
//your total_size is now (max_digits_size + 1) + msg_size

//first you retrieve from sm the number as string in number_memcopied var, then you convert:
const int retrieved_size = strtol(number_memcopied, NULL, 10);

【讨论】:

  • 当文件格式指定数字将被 ascii 编码时,这会读取数字的二进制编码。
  • 工作得很好,但我不确定@JoshWilson 的意图。该程序可以满足我的要求。
  • 如果你得到上面的代码并将"this is my data"替换为"{1.3.4.5.10.1.1 : [ok, string]}",它就会工作。还使用以数字开头的字符串检查了上面的代码并且也有效。在设置数据缓冲区时检查您是否移动了正确的大小。随机数可能是一些内存垃圾。检查您在处理字符串时是否考虑使用 \0 字符。这是关于没有在正确的内存块中获得正确的大小。
  • 使用 Visual Studio 内存窗口帮助您检查数据缓冲区。
猜你喜欢
  • 2021-11-15
  • 2013-06-23
  • 2016-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-25
  • 1970-01-01
相关资源
最近更新 更多