CreateFileMapping错误代码8

时间:2015-09-21 10:26:32

标签: c++ winapi memory file-mapping

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

2 个答案:

答案 0 :(得分:4)

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

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

不要使用这些宏。您可以使用LARGE_INTEGER替代:

LARGE_INTEGER size;
size.QuadPart = UBS_MEM_SIZE;
HANDLE hMapObject = CreateFileMapping(..., size.HighPart, size.LowPart, ...);

答案 1 :(得分:3)

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

HIWORD(UBS_MEM_SIZE)LOWORD(UBS_MEM_SIZE)都会产生0xffff(两个16位的一半),然后将它们转换为32位无符号整数(这是函数所期望的)。 / p>

因此,您实际要做的是要求提供大小为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"));

如果您确实需要处理超过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);
}

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