简体   繁体   English

具有结构映射向量的结构

[英]Struct having vector of structs mmapped

I am trying out this scenario - write a struct (multiple instances) which has a vector of struct to mmapped file and read from mmapped file. 我正在尝试这种情况-将一个具有结构向量的结构(多个实例)写入映射文件并从映射文件中读取。

In the below code; 在下面的代码中; when readFromMemMap() is called from the same program execution context, the read seems to be successful. 当从同一程序执行上下文中调用readFromMemMap()时,读取似乎成功。 But if I move readFromMemMap() to a different cpp file and run; 但是,如果我将readFromMemMap()移到另一个cpp文件并运行; then seg fault error occurs. 然后发生段错误错误。

Thanks for any pointers/inputs to resolve this. 感谢您提供任何指针/输入来解决此问题。

Code

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

Compile

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

Output 产量

$ ./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

readFromMemMap() in another cpp file 其他cpp文件中的readFromMemMap()

 $ ./readFromMemMap
   Reading from mmap

   FileSize = 240
       Size of struct Coords =24
   Reading from mmap : 1 Coords vector size = 4
   Segmentation fault

Each process have their own virtual memory. 每个进程都有自己的虚拟内存。 One process can not access the memory of another process (except in some platform specific ways, but those cases do not apply to dynamic memory). 一个进程无法访问另一进程的内存(某些平台特定的方式除外,但是那些情况不适用于动态内存)。

std::vector allocates its internal array using std::allocator by default. 默认情况下, std::vector使用std::allocator分配其内部数组。 std::allocator allocates dynamic memory. std::allocator分配动态内存。 When you write a vector to a file, that vector will refer to dynamic memory of the process that writes the vector. 当您将向量写入文件时,该向量将指向写入向量的进程的动态内存。 If you try to read that vector in another process, then that process has not allocated any dynamic memory in the virtual memory location where the original process had (unless by pure chance). 如果尝试在另一个进程中读取该向量,则该进程尚未在原始进程所在的虚拟内存位置中分配任何动态内存(除非有偶然的机会)。 Therefore using such vector has undefined behaviour. 因此,使用这种向量具有不确定的行为。

Objects whose state is stored in dynamic memory cannot be shared between processes. 状态存储在动态内存中的对象无法在进程之间共享。


To share an array between processes, you need to us a flat array rather than a vector. 要在进程之间共享数组,您需要我们使用平面数组而不是向量。

However, keep in mind that the size of an array that is a member of a class cannot be determined at run time. 但是,请记住,不能在运行时确定作为类成员的数组的大小。 Therefore if you need that size to be dynamic, you need to create the array as a non-member. 因此,如果您需要动态调整该大小,则需要将数组创建为非成员。


Furthermore, on line 此外,在线

map[x] = c;

You copy assign to map[x] where you haven't actually yet created a Coord object. 您将assign复制到尚未实际创建Coord对象的map[x] This has undefined behaviour since Coord is not trivially copyable. 由于Coord不可复制,因此具有不确定的行为。 It has been purely bad luck that even the writer code didn't crash. 甚至连编写者代码都没有崩溃,这纯属不幸。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM