【发布时间】:2020-03-20 23:57:48
【问题描述】:
所以,我有一个文件映射对象(64KB)和该映射的视图(在偏移量 0 处也是 64KB)。
当我写视图时,我先写要写的数据的长度,然后再写数据(这样我就可以通过先读长度,再读那个字节数来读取数据)
出于某种原因,此代码仅在写入 16KB 之前的偏移量时才有效(使用 16383 的偏移量有效,16384 出现内存冲突)。
代码如下:
LIB_EXPORT bool mem_write_to_view(mem_mapview_p view, DWORD offset, unsigned char *bytes, int len)
{
__try
{
((LPDWORD)(view->data))[offset] = len; // access violation only on this line; if I remove this line, it will write all the way up to 64KB
int sizeOfLen = sizeof(DWORD) / sizeof(char);
for (int i = 0; i < len; i++)
{
((char *)(view->data))[i + offset + sizeOfLen] = bytes[i];
}
}
__except (GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_EXECUTION)
{
printf("ERROR: error\r\n");
report_last(view->reporter, "mem_write_to_view");
report_last_explicit(view->reporter, "mem_write_to_view", "Failed to write to view.");
return false;
}
return true;
}
正如代码中的注释所示,当我尝试设置长度时,我只会遇到访问冲突(在 16KB 之后,再次,这在 16KB 之前有效,我不知道为什么),否则,我可以使用这种方法一直写到地图视图的末尾(因此这个问题的标题“只能将 char* 写入 LPVOID 缓冲区”)
view->data 用这一行初始化:
view->data = MapViewOfFile(map->hMap, FILE_MAP_ALL_ACCESS, offset_hi, offset_lo, size); 在调用 mem_write_to_view 之前。
知道为什么会发生这种情况(更具体地说,为什么它只发生在 16KB+ 的偏移量处)?
我在MapViewOfFile 返回的 LPVOID 指针上运行了VirtualQuery,并确认它的大小确实为 64KB。
我真的对低级内存访问一无所知(我来自高级面向对象的背景),所以我不知道将LPVOID 解释为LPDWORD 可能会导致什么问题然后将其解释为char *,但我很确定这是在数据前面写入长度的唯一方法,对吧?
【问题讨论】: