Итак, у меня есть объект сопоставления файлов (это 64 КБ) и представление этого сопоставления (оно также 64 КБ со смещением 0).
Когда я записываю в представление, я сначала записываю длину данные для записи, затем я записываю данные (чтобы я мог прочитать данные, сначала прочитав длину, а затем прочитав это количество байтов)
По какой-то причине этот код работает только при записи в смещения до 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;
}
Как видно из комментария в коде, я получаю нарушение прав доступа только при попытке установить длину (после 16 КБ, опять же, это работает до 16KB, я не уверен, почему), в противном случае, я могу использовать этот метод для записи до конца представления карты (отсюда и заголовок этого вопроса: «Можно только записать char * в буфер LPVOID»)
view->data
инициализируется этой строкой: view->data = MapViewOfFile(map->hMap, FILE_MAP_ALL_ACCESS, offset_hi, offset_lo, size);
до вызова mem_write_to_view
.
Любая идея, почему это происходит (а также, более конкретно, почему это происходит только при смещениях 16KB +)?
Я запустил VirtualQuery
на указателе LPVOID, возвращенном MapViewOfFile
, и подтвердил, что он действительно имеет размер 64KB.
Я действительно мало что знаю о низкоуровневом доступе к памяти (я имею в виду, в основном, высокоуровневый объектно-ориентированный фон), поэтому я понятия не имею, какие проблемы я могу вызвать, интерпретируя LPVOID
как LPDWORD
и затем интерпретировать его как char *
, но я почти уверен, что это единственный способ записать длину перед данными, верно?