Код ошибки CreateFileMapping 8. Недостаточно памяти для обработки этой команды. Я пытаюсь создать сопоставление файлов с 4 ГБ (0xFFFFFFFF) на 64-битной Win10 Visual C ++.
#define UBS_MEM_SIZE 0xffffffff
HANDLE hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr,
PAGE_READWRITE, HIWORD(UBS_MEM_SIZE), LOWORD(UBS_MEM_SIZE),
TEXT("dllmemfilemap"));
Как я могу решить эту проблему «ОШИБКА 8»?
CreateFileMapping(..., HIWORD(UBS_MEM_SIZE), LOWORD(UBS_MEM_SIZE), ...)
Макросы LO / HIWORD генерируют WORD, 16-битное значение. Вы запрашиваете отображенный в памяти файл 0xffff0000ffff. Это 282 терабайта. Текущие процессоры x64 ограничены 48-битным виртуальным адресом, максимальный размер которого составляет 8 терабайт. Так что да, ошибка 8 (ERROR_NOT_ENOUGH_MEMORY) вполне ожидаема.
Не используйте эти макросы. Вы можете использовать LARGE_INTEGER в качестве альтернативы:
LARGE_INTEGER size;
size.QuadPart = UBS_MEM_SIZE;
HANDLE hMapObject = CreateFileMapping(..., size.HighPart, size.LowPart, ...);
HIWORD
а также LOWORD
макросы предназначены для извлечения старших и младших 16-битных слов из 32-битных DWORD
, CreateFileMapping
с другой стороны, ожидает двух DWORD
s вместе составляют 64-битное целое число без знака, которое является размером объекта сопоставления.
И то и другое HIWORD(UBS_MEM_SIZE)
а также LOWORD(UBS_MEM_SIZE)
Уступать 0xffff
(две 16-битные половины), которые затем преобразуются в 32-битные целые числа без знака (что и ожидает функция).
Итак, что вы на самом деле делаете, так это запрашиваете отображение размера файла 0x0000ffff0000ffff
, Это больше чем 255 TB
, Так как вы используете INVALID_HANDLE_VALUE
это должно быть подкреплено ОЗУ или файлом системной страницы; Я сомневаюсь, что у вас есть так много там
Если UBS_MEM_SIZE
всегда 32-битный, вы можете просто использовать
HANDLE hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr,
PAGE_READWRITE, 0, UBS_MEM_SIZE,
TEXT("dllmemfilemap"));
Если вам действительно нужно обрабатывать размеры более 4 GB
Вы можете сделать что-то вроде этого:
HANDLE hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE,
static_cast<DWORD>(UBS_MEM_SIZE >> 32), static_cast<DWORD>(UBS_MEM_SIZE),
TEXT("dllmemfilemap"));
Удостовериться UBS_MEM_SIZE
на самом деле имеет тип больше 32-битного (даже если его значение может быть меньше этого), так как в противном случае сдвиг на 32 бита — неопределенное поведение в C ++. Итак, если вы хотите использовать второй вариант выше с вашим начальным значением, это должно быть что-то вроде
#define UBS_MEM_SIZE 0xFFFFFFFFull
(Кстати, используйте const
…)
Чтобы сделать его более безопасным, я бы обернул вызов примерно так:
inline HANDLE MyCreateMapping(unsigned long long size, LPCTSTR name)
{
return CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE,
static_cast<DWORD>(size >> 32), static_cast<DWORD>(size), name);
}
Таким образом, вам не нужно запоминать хитрые детали о битах, сдвигах и размерах целочисленных типов.