Smit Ycyken
Smit Ycyken

Reputation: 1207

CreateFileMapping error code 8

CreateFileMapping error code 8.Not enough storage is available to process this command. Im trying to create file mapping with 4 Gb (0xFFFFFFFF) on 64bit 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"));

How can i solve this "ERROR 8" problem?

Upvotes: 1

Views: 1670

Answers (2)

Hans Passant
Hans Passant

Reputation: 941465

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

The LO/HIWORD macros generate a WORD, a 16-bit value. You are asking for a 0xffff0000ffff memory-mapped file. That's 282 terabytes. Current x64 processors are limited to a 48-bit VM-address, most top out at 8 terabytes. So yes, error 8 (ERROR_NOT_ENOUGH_MEMORY) is entirely expected.

Don't use those macros. You can use LARGE_INTEGER as an alternative:

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

Upvotes: 5

bogdan
bogdan

Reputation: 9317

The HIWORD and LOWORD macros are intended to extract the high and low 16-bit words from a 32-bit DWORD. CreateFileMapping, on the other hand, expects two DWORDs that together make up a 64-bit unsigned integer, which is the size of the mapping object.

Both HIWORD(UBS_MEM_SIZE) and LOWORD(UBS_MEM_SIZE) yield 0xffff (the two 16-bit halves), which are then converted to 32-bit unsigned integers (which is what the function expects).

So, what you're actually doing is asking for a file mapping of size 0x0000ffff0000ffff. This is more than 255 TB. Since you're using INVALID_HANDLE_VALUE, this has to be backed by RAM or the system page file; I doubt you have that much available in there.

If UBS_MEM_SIZE is always 32-bit, you can simply use

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

If you actually need to handle sizes over 4 GB, you can do something like this:

HANDLE hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 
   static_cast<DWORD>(UBS_MEM_SIZE >> 32), static_cast<DWORD>(UBS_MEM_SIZE), 
   TEXT("dllmemfilemap"));

Make sure UBS_MEM_SIZE actually has a type larger than 32-bit (even if its value may be less than that), since otherwise shifting by 32 bits is undefined behaviour in C++. So, if you want to use the second variant above with your initial value, it will have to be something like

#define UBS_MEM_SIZE 0xFFFFFFFFull

(By the way, use const...)

To make it safer, I'd wrap the call into something like this:

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

This way, you don't need to remember any tricky details about bits, shifts and integer type sizes.

Upvotes: 4

Related Questions