C ++ MapViewOfFile выдает ошибку (5 доступ запрещен) при попытке отобразить представление, размер которого превышает 1/2 размера файла, все, что меньше 1/2, возвращает действительный дескриптор - PullRequest
0 голосов
/ 14 октября 2018

Я построил этот класс из примера MSDN здесь , и он работает нормально, пока не попытается собрать данные с позиции в середине файла.Неважно, насколько большой я создаю файл, будь то 1 МБ или 512 МБ, все, что больше 1/2, приводит к сбою отображения представления с ошибкой (5), доступ запрещен.

-Предназначен для базы данных, поэтому он состоит из 128-байтовых блоков

-Компилятор использует кодовые блоки с использованием c ++ 11

-Система Win10 64bit

Пример, воссоздающий ошибку:

//Create the map object.
c_NT3_MMap tmp_Map;

//The array to hold the data retrieved.
char tmp_Data[128];

//Open the file "example.dat" with a size of 1MB.
//Predicted max 128 byte chunks = ((1 * (1024 * 1024)) / 128) = 8192
tmp_Map.open_File("example.dat", 1);

//Getting the chunk 4096 which is 1/2 of the computed max works fine.
tmp_Map.get_Chunk(4096, tmp_Data);

//This does not, throws an error code 5 and the map view == NULL.
tmp_Map.get_Chunk(4097, tmp_Data);

Класс для управления отображенным в память объектом:

 class c_NT3_MMap
 {
 private:

      //Size of the memory chunk.
      const int CONST_BUFFER_SIZE = 128;

      //The temporary character array to hold the current node.
      char Data[128];

      //The file to open.
      HANDLE Data_File;

      //Handle to the mapped file
      HANDLE MMap_File_Mapping;

      //Handle to the mapped file view
      HANDLE MMap_View;

      //System information. Used to get the system granularity.
      SYSTEM_INFO system_Info;
      DWORD system_Granulation;

      //Get the nearest multiple of system grains to the starting offset. Where to start the mapping.
      DWORD MMap_Starting_Offset;

      //The size of the file mapping view.
      //MMap_View_Size = (MMap_Starting_Offset % system_Granulation) + BUFFSIZE
      DWORD MMap_View_Size;

      //The size of the file mapping object.
      DWORD MMap_File_Map_Size;

      //The current position of the data pointer in the file.
      unsigned long long int MMap_Current_Position;

      //The current filename opened
      string File_Name;

 public:

      string file_Name;

      void * MMap_Current_Position_Data;

      c_NT3_MMap()
      {
           Data_File = NULL;
           MMap_Current_Position = 0;
           MMap_File_Map_Size = 0;
           MMap_File_Mapping = NULL;
           MMap_Starting_Offset = 0;
           MMap_View = NULL;
           MMap_View_Size = 0;
           File_Name = "NOFILE";
      }


      void get_System_Granulation()
      {
           // Get the system allocation granularity.
           GetSystemInfo(&system_Info);
           system_Granulation = system_Info.dwAllocationGranularity;

      }

      //p_Map_Size is MB
      void calculate_Mapping_Parameters(unsigned long long int p_Map_Size = 512)
      {
           cout << "\n p_Map_Size->" << p_Map_Size;

           //Get the system granulation.
           get_System_Granulation();

           cout << "\n system_Granulation->" << system_Granulation;

           //Get the MMap_Starting_Offset for where to start the mapping in the file grains.
           MMap_Starting_Offset = 0;//(p_File_Map_Start / system_Granulation) * system_Granulation;

           cout << "\n MMap_Starting_Offset->" << MMap_Starting_Offset;

           //Calculate the size of the mapping view.
           MMap_View_Size = CONST_BUFFER_SIZE;//(p_File_Map_Start % system_Granulation) + CONST_BUFFER_SIZE;

           cout << "\n MMap_View_Size->" << MMap_View_Size;

           //Figure size of the file mapping object.
           MMap_File_Map_Size = (p_Map_Size * (1024 * 1024)) + CONST_BUFFER_SIZE;

           cout << "\n MMap_File_Map_Size->" << MMap_File_Map_Size;

           //Find the current position of the data pointer to use when referencing file contents.
           MMap_Current_Position = MMap_Starting_Offset;

           cout << "\n MMap_Current_Position->" << MMap_Current_Position;
      }

      //Maps the files, does not create the view.
      int create_Mapping()
      {
           MMap_File_Mapping = CreateFileMapping(Data_File,          // current file handle
                NULL,           // default security
                PAGE_READWRITE, // read/write permission
                0,              // size of mapping object, high
                MMap_File_Map_Size,  // size of mapping object, low
                NULL);  

           if (MMap_File_Mapping == NULL)
           {
                cout << "\n MMap_File_Mapping == NULL LastError():" << GetLastError();
                return 2;
           }

           return 1;
      }


      void calculate_View_Parameters(unsigned long long int p_Position)
      {
           //Get the MMap_Starting_Offset for where to start the mapping in the file grains.
           MMap_Starting_Offset = (p_Position / system_Granulation) * system_Granulation;

           cout << "\n MMap_Starting_Offset->" << MMap_Starting_Offset;

           //Calculate the size of the mapping view.
           MMap_View_Size = (p_Position - ((unsigned long long int) (p_Position / system_Granulation))) + CONST_BUFFER_SIZE;

           cout << "\n MMap_View_Size->" << MMap_View_Size;

           MMap_Current_Position = p_Position;

           cout << "\n MMap_Current_Position->" << MMap_Current_Position;
      }

      //Creates a view at the given offset.
      int create_Mapping_View(unsigned long long int p_Position = 0)
      {
           calculate_View_Parameters(p_Position);

           //Do this in case a view is already mapped.
           if (MMap_View != NULL)
           {
                UnmapViewOfFile(MMap_View);
                MMap_View = NULL;
           }

           MMap_View = MapViewOfFile(MMap_File_Mapping,            // handle to
                                 // mapping object
                FILE_MAP_ALL_ACCESS, // read/write
                0,                   // high-order 32
                                    // bits of file
                                    // offset
                MMap_Starting_Offset,      // low-order 32
                                    // bits of file
                                    // offset
                MMap_View_Size);      // number of bytes
                                    // to map

           if (MMap_View == NULL)
           {
                cout << "\n MMap_View == NULL LastError():" << GetLastError();
                return 3;
           }

           MMap_Current_Position_Data = ((char*) MMap_View + MMap_Current_Position);
           return 1;
      }

      //The p_File_Map_Start is the offset to use in the beginning. 
      //There will be a function for moving the view.
      int open_File(string p_File_Name, unsigned long long int p_Map_Size_MB = 512)
      {

           Data_File = NULL;

           File_Name = p_File_Name;

           cout << "\n Opening " << p_File_Name;

           calculate_Mapping_Parameters(p_Map_Size_MB);

           Data_File = CreateFile(p_File_Name.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

           //Map the file
           create_Mapping();

           //Create the view.
           create_Mapping_View(0);

           //Determine if the mapping was a success.
           if (MMap_Current_Position_Data == NULL){ return 0; }

           return 1;
      }

      void close()
      {
           UnmapViewOfFile(MMap_View);
           CloseHandle(MMap_File_Mapping); 
           CloseHandle(Data_File);   
      }

      void save_Data()
      {
           FlushViewOfFile(MMap_Current_Position_Data, 128);
      }

      //Gets the current datas.
      void get_Data(char * p_Data)
      {                  
           if (MMap_View == NULL)
           {
                cout << "\n MMap_View == NULL LastError():" << GetLastError();
                return;
           }
           for (int cou_Index=0;cou_Index<128;cou_Index++)
           {
                p_Data[cou_Index] = ((char*)MMap_Current_Position_Data)[cou_Index];
           }
      }

      //Gets a 128 byte chunk.
      void get_Chunk(unsigned long long int p_Position, char * p_Data)
      {
           //Multiply by 128 to get the chunk position, not byte position.
           create_Mapping_View(p_Position * 128);
           get_Data(p_Data);
      }
 };

Краткий список некоторых ответов, которые я нашел, но неотноситесь к моей проблеме.

есть ли какое-либо ограничение для использования mapviewoffile Это он пытался отобразить весь файл и ему не хватило памяти

c-createfilemapping-error-5-access-denied-всегда Я не получаю сообщение об ошибке каждый раз, только при доступе ко второй половине блока.

mapviewoffile-return-error-5-error-access-denied Его проблема, похоже, немного другая.Он пытается установить связь между 32-разрядным процессом и 64-разрядным процессом, и его ошибка возникает, когда 32-разрядный процесс создает сопоставление.Я пытаюсь работать с одним файлом с помощью одного процесса.

Глядя на другие ответы, кажется, что у меня где-то неправильные размеры, но из-за жизни я не могу понять, где.

...