1

CreateFileMapping 错误代码 8.没有足够的存储空间来处理此命令。我试图在 64 位 Win10 Visual C++ 上创建具有 4 Gb (0xFFFFFFFF) 的文件映射。

#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”问题?

4

2 回答 2

5
   CreateFileMapping(..., HIWORD(UBS_MEM_SIZE), LOWORD(UBS_MEM_SIZE), ...)

LO/HIWORD 宏生成一个 WORD,一个 16 位的值。您要求一个 0xffff0000ffff 内存映射文件。那是 282 TB。当前的 x64 处理器仅限于 48 位 VM 地址,大多数最高为 8 TB。所以是的,完全可以预料到错误 8 (ERROR_NOT_ENOUGH_MEMORY)。

不要使用那些宏。您可以使用 LARGE_INTEGER 作为替代方案:

LARGE_INTEGER size;
size.QuadPart = UBS_MEM_SIZE;
HANDLE hMapObject = CreateFileMapping(..., size.HighPart, size.LowPart, ...);
于 2015-09-21T12:58:01.730 回答
4

HIWORDLOWORD宏旨在从 32 位中提取高 16 位字和低 16 位字DWORDCreateFileMapping另一方面,期望两个DWORDs 一起组成一个 64 位无符号整数,即映射对象的大小。

HIWORD(UBS_MEM_SIZE)LOWORD(UBS_MEM_SIZE)yield (两个0xffff16 位的一半),然后转换为 32 位无符号整数(这是函数所期望的)。

所以,你实际上在做的是要求一个 size 的文件映射0x0000ffff0000ffff。这比255 TB. 由于您使用的是INVALID_HANDLE_VALUE,这必须由 RAM 或系统页面文件支持;我怀疑你那里有那么多可用的东西。

如果UBS_MEM_SIZE始终是 32 位,您可以简单地使用

HANDLE hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr,
   PAGE_READWRITE, 0, UBS_MEM_SIZE,
   TEXT("dllmemfilemap"));

如果您确实需要处理 size over 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 位的类型(即使它的值可能小于该值),因为否则在 C++ 中移位 32 位是未定义的行为。所以,如果你想使用上面的第二个变体和你的初始值,它必须是这样的

#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);
}

这样,您无需记住有关位、移位和整数类型大小的任何棘手细节。

于 2015-09-21T12:58:00.060 回答