代码之家  ›  专栏  ›  技术社区  ›  PaperMoon

具有结构mmapped向量的结构

  •  0
  • PaperMoon  · 技术社区  · 7 年前

    我正在尝试这个场景-编写一个结构(多个实例),其中有一个指向MMAP文件的结构向量,并从MMAP文件中读取。

    在以下代码中;当从同一程序执行上下文调用readFromMemMap()时,读取似乎成功。但如果我将readFromMemMap()移动到另一个cpp文件并运行;然后出现seg故障错误。

    密码

    #include <iostream>
    #include <cstdlib>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    #include <vector>
    
    #define FILEPATH "/tmp/mmapped.bin"
    #define NUMINTS  (10)
    
    struct _3DVec
    {
      int x;
      int y;
      int z;
    };
    
    struct Coords
    {
      std::vector<_3DVec> coords;
    };
    
    void readFromMemMap()
    {
      std::cout << "\n----------------------------------\n" << std::endl;
    
      int fileSize = NUMINTS * sizeof(Coords);
      std::cout << "Reading from mmapped file\n" << std::endl;
    
      std::cout << "FileSize = " << fileSize << "\n\tSize of struct Coords =" << sizeof(Coords) << std::endl;
    
      int i;
      int fd;
      Coords *map;
    
      fd = open(FILEPATH, O_RDONLY);
      if (fd == -1) 
      {
        std::cerr << "Error opening file for reading" << std::endl;
        exit(EXIT_FAILURE);
      }
    
      map = (Coords*)mmap(0, fileSize, PROT_READ, MAP_SHARED, fd, 0);
    
      if (map == MAP_FAILED) 
      {
       close(fd);
       std::cerr << "Error mmapping the file" << std::endl;
       exit(EXIT_FAILURE);
      }
    
      /* Read the file from the mmap  */
      for (i = 1; i <=3; ++i) 
      {
        std::cout << "Reading from mmap : " << i << " Coords vector size = "  << map[i].coords.size() << std::endl;
    
        for (_3DVec v : map[i].coords)
        {
          std::cout << " x=" <<  v.x << ", y=" <<  v.y << ", z=" << v.z << std::endl;
        }
      }
    
      if (munmap(map, fileSize) == -1) 
      {
        std::cerr << "Error un-mmapping the file" << std::endl;
      }
      close(fd);
     }
    
    int main(int argc, char *argv[])
    {
      int fileSize = NUMINTS * sizeof(Coords);
    
      std::cout << "Writing to mmapped file " << std::endl;
      std::cout << "For writing, fileSize = " << fileSize << " \n\tSize of struct Coords =" << sizeof(Coords) << std::endl;
    
      int i;
      int fd;
      int result;
    
      Coords *map;  /* mmapped array of Coords's */
    
      fd = open(FILEPATH, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
      if (fd == -1) 
      {
        std::cerr << "Error opening file for writing" << std::endl;
        exit(EXIT_FAILURE);
      }
    
      /* Stretch the file size to the size of the (mmapped) array of ints*/
      result = lseek(fd, fileSize-1, SEEK_SET);
      if (result == -1) 
      {
        close(fd);
        std::cerr << "Error calling lseek() to 'stretch' the file" << std::endl;
        exit(EXIT_FAILURE);
      }
    
      result = write(fd, "", 1);
      if (result != 1) 
      {
        close(fd);
        std::cerr << "Error writing last byte of the file" << std::endl;
        exit(EXIT_FAILURE);
      }
    
      /* Now the file is ready to be mmapped.*/
      map = (Coords*)mmap(0, fileSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
      if (map == MAP_FAILED) 
      {
        close(fd);
        std::cerr << "Error mmapping the file" << std::endl;
        exit(EXIT_FAILURE);
      }
    
      /* Now write to mmapped file*/
    
     for (int x=1; x<=3; ++x)
     {
       Coords c;
    
       for (i = 1; i <=4; ++i)
      {
         _3DVec v;
    
         v.x = i;
         v.y = i*2;
         v.z = i*3;      
    
         c.coords.push_back(v);
        }
        map[x] = c; 
      }
    
      /* Don't forget to free the mmapped memory */
      if (munmap(map, fileSize) == -1) 
      {
        std::cerr << "Error un-mmapping the file" << std::endl; 
      }
    
      /* Un-mmaping doesn't close the file, so we still need to do that.*/
      close(fd);
    
      readFromMemMap();
    
      return 0;
    }
    

    编写

     g++ writeToMemMap.cpp -o writeToMemMap -std=c++11
    

    $ ./writeToMemMap
    Writing to mmapped file 
    For writing, fileSize = 240 
        Size of struct Coords =24
    
    ----------------------------------
    
    Reading from mmapped file
    
    FileSize = 240
        Size of struct Coords =24
    Reading from mmap : 1 Coords vector size = 4
    x=1, y=2, z=3
    x=2, y=4, z=6
    x=3, y=6, z=9
    x=4, y=8, z=12
    Reading from mmap : 2 Coords vector size = 4
    x=1, y=2, z=3
    x=2, y=4, z=6
    x=3, y=6, z=9
    x=4, y=8, z=12
    Reading from mmap : 3 Coords vector size = 4
    x=1, y=2, z=3
    x=2, y=4, z=6
    x=3, y=6, z=9
    x=4, y=8, z=12
    

    另一个cpp文件中的readFromMemMap()

     $ ./readFromMemMap
       Reading from mmap
    
       FileSize = 240
           Size of struct Coords =24
       Reading from mmap : 1 Coords vector size = 4
       Segmentation fault
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   eerorika    7 年前

    每个进程都有自己的虚拟内存。一个进程无法访问另一个进程的内存(除非以某些特定于平台的方式,但这些情况不适用于动态内存)。

    std::vector std::allocator 默认情况下。 std::分配器 分配动态内存。将向量写入文件时,该向量将指写入向量的进程的动态内存。如果您尝试在另一个进程中读取该向量,则该进程在原始进程所在的虚拟内存位置中没有分配任何动态内存(除非纯粹是偶然)。因此,使用这种向量具有未定义的行为。

    状态存储在动态内存中的对象不能在进程之间共享。



    此外,在线

    map[x] = c;
    

    您复制分配给 map[x] Coord 对象自那时起,这种行为尚未定义 坐标