Одна из возможностей заключается в том, что вы не используете смещение, кратное гранулярности распределения. Из MSDN:
Комбинация верхнего и нижнего смещений должна указывать смещение в отображении файла. Они также должны соответствовать гранулярности распределения памяти системы. То есть смещение должно быть кратным гранулярности распределения. Чтобы получить детализацию выделения памяти системы, используйте функцию GetSystemInfo, которая заполняет члены структуры SYSTEM_INFO.
Если вы попытаетесь отобразить что-то, отличное от кратности гранулярности распределения, сопоставление завершится неудачно и GetLastError
вернет ERROR_MAPPED_ALIGNMENT
.
Кроме этого, в примере кода есть много проблем, из-за которых очень трудно увидеть, что вы пытаетесь сделать, и в чем дело. Как минимум, вам нужно решить утечки памяти. Вы, кажется, распределяете, а затем пропускаете совершенно ненужные буферы. Если дать им более подходящие имена, можно понять, для чего они на самом деле используются.
Затем я предлагаю поставить точку останова на вызовах MapViewOfFile, а затем проверить все значения параметров, которые вы передаете, чтобы убедиться, что они выглядят правильно. Для начала при втором вызове можно ожидать, что offsetHigh будет 0, а offsetLow будет bufferSize.
Несколько подозрительных вещей вне летучей мыши:
HANDLE inputFile = (HANDLE)OpenFile(inputFileName, &tOfStr, OF_READ);
Каждый актерский состав должен вызывать у вас подозрения. Иногда они необходимы, но убедитесь, что вы понимаете, почему. В этот момент вы должны спросить себя, почему для каждого используемого вами файлового API требуется HANDLE
, а эта функция возвращает HFILE
. Если вы посмотрите документацию OpenFile , вы увидите: «Эта функция имеет ограниченные возможности и не рекомендуется. Для разработки новых приложений используйте функцию CreateFile». Я знаю, это звучит странно, потому что вы хотите открыть существующий файл, но CreateFile может сделать именно это, и он возвращает правильный тип.
long long offsetHigh = ((offset >> 32) & 0xFFFFFFFF);
Какой тип offset
? Вы, вероятно, хотите убедиться, что это unsigned long long
или эквивалент. При сдвиге битов, особенно вправо, вы почти всегда хотите, чтобы беззнаковый тип избегал расширения знака. Вы также должны убедиться, что этот тип имеет больше битов, чем количество, на которое вы сдвигаете - сдвиг 32-битного значения на 32 (или более) битов фактически не определен в C и C ++, что позволяет компиляторам сделать определенные типы оптимизаций.
long long offsetLow = (offset & 0xFFFFFFFF);
В обоих этих утверждениях вы должны быть осторожны со значением 0xFFFFFFFF
. Поскольку вы не приводили его или не присваивали ему суффикс, может быть трудно предсказать, будет ли компилятор рассматривать его как int или беззнаковое int. В этом случае,
это будет неподписанный int, но это не будет очевидно для многих людей. По факту,
Я неправильно понял, когда впервые написал этот ответ. [ Этот параграф исправлен 16-May-2017 ] С побитовыми операциями вы почти всегда хотите убедиться, что используете значения без знака.
tmp_buffer = (char *)MapViewOfFile(fileMap, FILE_MAP_READ, (int)offsetHigh, (int)offsetLow, bufferSize);
Вы приводите offsetHigh
и offsetLow
к int
с, которые являются знаковыми значениями. API фактически хочет DWORD
s, которые являются беззнаковыми значениями. Вместо приведения в вызове я объявил бы offsetHigh
и offsetLow
как DWORD
s и произвел бы приведение в инициализации, например так:
DWORD offsetHigh = static_cast<DWORD>((offset >> 32) & 0xFFFFFFFFul);
DWORD offsetLow = static_cast<DWORD>( offset & 0xFFFFFFFFul);
tmp_buffer = reinterpret_cast<const char *>(MapViewOfFile(fileMap, FILE_MAP_READ, offsetHigh, offsetLow, bufferSize));
Эти исправления могут или не могут решить вашу проблему. Трудно сказать, что происходит из неполного примера кода.
Вот рабочий пример, с которым вы можете сравнить:
// Calls ProcessChunk with each chunk of the file.
void ReadInChunks(const WCHAR *pszFileName) {
// Offsets must be a multiple of the system's allocation granularity. We
// guarantee this by making our view size equal to the allocation granularity.
SYSTEM_INFO sysinfo = {0};
::GetSystemInfo(&sysinfo);
DWORD cbView = sysinfo.dwAllocationGranularity;
HANDLE hfile = ::CreateFileW(pszFileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
if (hfile != INVALID_HANDLE_VALUE) {
LARGE_INTEGER file_size = {0};
::GetFileSizeEx(hfile, &file_size);
const unsigned long long cbFile =
static_cast<unsigned long long>(file_size.QuadPart);
HANDLE hmap = ::CreateFileMappingW(hfile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hmap != NULL) {
for (unsigned long long offset = 0; offset < cbFile; offset += cbView) {
DWORD high = static_cast<DWORD>((offset >> 32) & 0xFFFFFFFFul);
DWORD low = static_cast<DWORD>( offset & 0xFFFFFFFFul);
// The last view may be shorter.
if (offset + cbView > cbFile) {
cbView = static_cast<int>(cbFile - offset);
}
const char *pView = static_cast<const char *>(
::MapViewOfFile(hmap, FILE_MAP_READ, high, low, cbView));
if (pView != NULL) {
ProcessChunk(pView, cbView);
}
}
::CloseHandle(hmap);
}
::CloseHandle(hfile);
}
}