【问题标题】:CreateFileMapping error code 8CreateFileMapping 错误代码 8
【发布时间】:2015-12-18 00:21:31
【问题描述】:

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"));

如何解决这个“ERROR 8”问题?

【问题讨论】:

  • 您正在构建 64 位 exe 吗?
  • 是的,我尝试构建 64 和 86,同样的错误。但这有关系吗?
  • 是的,因为 32 位程序无法使用 4Gb。
  • 您是如何确定 16GB(或 GiB?)的虚拟内存的?虚拟内存空间与安装的 RAM 不对应。也就是说,错误8是什么意思? VC IDE 带有一个错误查找工具,使用它来查找!另外,使用这种方法可以成功映射的最大尺寸是多少?
  • 我的错,在 64 位中有 16 EB 的虚拟内存。

标签: c++ winapi memory file-mapping


【解决方案1】:
   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, ...);

【讨论】:

    【解决方案2】:

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

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

    所以,您实际上是在请求大小为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 位的类型(即使它的值可能小于该值),因为否则在 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);
    }
    

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

    【讨论】:

    • Ty 4 详细回复!
    猜你喜欢
    • 2018-02-11
    • 2011-04-29
    • 2017-01-18
    • 2016-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-05
    • 1970-01-01
    相关资源
    最近更新 更多