c++ - Struct having vector of structs mmapped -
i trying out scenario - write struct (multiple instances) has vector of struct mmapped file , read mmapped file.
in below code; when readfrommemmap() called same program execution context, read seems successful. if move readfrommemmap() different cpp file , run; seg fault error occurs.
thanks pointers/inputs 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 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 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 file" << std::endl; exit(exit_failure); } /* read file mmap */ (i = 1; <=3; ++i) { std::cout << "reading mmap : " << << " coords vector size = " << map[i].coords.size() << std::endl; (_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 file" << std::endl; } close(fd); } int main(int argc, char *argv[]) { int filesize = numints * sizeof(coords); std::cout << "writing 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 writing" << std::endl; exit(exit_failure); } /* stretch file size size of (mmapped) array of ints*/ result = lseek(fd, filesize-1, seek_set); if (result == -1) { close(fd); std::cerr << "error calling lseek() 'stretch' file" << std::endl; exit(exit_failure); } result = write(fd, "", 1); if (result != 1) { close(fd); std::cerr << "error writing last byte of file" << std::endl; exit(exit_failure); } /* file ready mmapped.*/ map = (coords*)mmap(0, filesize, prot_read | prot_write, map_shared, fd, 0); if (map == map_failed) { close(fd); std::cerr << "error mmapping file" << std::endl; exit(exit_failure); } /* write mmapped file*/ (int x=1; x<=3; ++x) { coords c; (i = 1; <=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 free mmapped memory */ if (munmap(map, filesize) == -1) { std::cerr << "error un-mmapping file" << std::endl; } /* un-mmaping doesn't close file, still need that.*/ close(fd); readfrommemmap(); return 0; } compile
g++ writetomemmap.cpp -o writetomemmap -std=c++11 output
$ ./writetomemmap writing mmapped file writing, filesize = 240 size of struct coords =24 ---------------------------------- reading mmapped file filesize = 240 size of struct coords =24 reading 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 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 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 cpp file
$ ./readfrommemmap reading mmap filesize = 240 size of struct coords =24 reading mmap : 1 coords vector size = 4 segmentation fault
each process have own virtual memory. 1 process can not access memory of process (except in platform specific ways, cases not apply dynamic memory).
std::vector allocates internal array using std::allocator default. std::allocator allocates dynamic memory. when write vector file, vector refer dynamic memory of process writes vector. if try read vector in process, process has not allocated dynamic memory in virtual memory location original process had (unless pure chance). therefore using such vector has undefined behaviour.
objects state stored in dynamic memory cannot shared between processes.
to share array between processes, need flat array rather vector.
however, keep in mind size of array member of class cannot determined @ run time. therefore if need size dynamic, need create array non-member.
furthermore, on line
map[x] = c; you copy assign map[x] haven't yet created coord object. has undefined behaviour since coord not trivially copyable. has been purely bad luck writer code didn't crash.
Comments
Post a Comment