c++ - SharedMemory container problems -
i've created following code testing shared memory allocators , containers..
the allocator (basic allocator keeps pointer memory block + size:
template<typename t> struct sharedmemoryallocator { typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef t* pointer; typedef const t* const_pointer; typedef t& reference; typedef const t& const_reference; typedef t value_type; void* memory; std::size_t size; sharedmemoryallocator(void* memory, std::size_t size) noexcept : memory(memory), size(size) {}; sharedmemoryallocator(const sharedmemoryallocator& other) noexcept : memory(other.memory), size(other.size) {}; template<typename u> sharedmemoryallocator(const sharedmemoryallocator<u>& other) noexcept : memory(other.memory), size(other.size) {}; template<typename u> sharedmemoryallocator& operator = (const sharedmemoryallocator<u>& other) { return *this; } sharedmemoryallocator<t>& operator = (const sharedmemoryallocator& other) { return *this; } ~sharedmemoryallocator() {} pointer address(reference value) const {return &value;} const_pointer address(const_reference value) const {return &value;} pointer allocate(size_type n, const void* hint = 0) {return static_cast<t*>(memory);} void deallocate(t* ptr, size_type n) {} template<typename u, typename... args> void construct(u* ptr, args&&... args) {::new(static_cast<void*>(ptr)) u(std::forward<args>(args)...);} void construct(pointer ptr, const t& val) {new(static_cast<t*>(ptr)) t(val);} template<typename u> void destroy(u* ptr) {ptr->~u();} void destroy(pointer ptr) {ptr->~t();} size_type max_size() const {return size / sizeof(t);} template<typename u> struct rebind {typedef sharedmemoryallocator<u> other;}; }; template <typename t, typename u> inline bool operator == (const sharedmemoryallocator<t>& a, const sharedmemoryallocator<u>& b) { return (a == b); } template <typename t, typename u> inline bool operator != (const sharedmemoryallocator<t>& a, const sharedmemoryallocator<u>& b) { return !(a == b); }
the container (just container allocates memory using sharedmemory allocator):
template<typename t, typename allocator = std::allocator<t>> class cvector { private: t* memory; std::size_t size, capacity; allocator alloc; public: cvector() : memory(nullptr), size(0), capacity(0), alloc(allocator()) {} cvector(const allocator &alloc) : memory(nullptr), size(0), capacity(0), alloc(alloc) {} ~cvector() { if(memory) { for(std::size_t = 0; < this->size; ++i) { alloc.destroy(memory + i); } alloc.deallocate(memory, capacity); memory = nullptr; } } void reserve(std::size_t size) { if(capacity < size) { capacity = size; void* mem = alloc.allocate(capacity); if(memory && memory != mem) { memcpy(static_cast<char*>(mem), memory, size * sizeof(t)); for(std::size_t = 0; < this->size; ++i) { alloc.destroy(memory + i); } alloc.deallocate(memory, capacity); memory = nullptr; } memory = static_cast<t*>(mem); } } void push_back(t&& value) { if(capacity == 0) { reserve(1); } if(size >= capacity) { reserve(capacity * 2); } alloc.construct(memory + size++, value); } t& operator[](std::size_t size) { return *(memory + size); } const t& operator[](std::size_t size) const { return *(memory + size); } };
main:
int main() { memorymap mem{"local\\test", 5000, std::ios::in | std::ios::out}; mem.open(); mem.map(); typedef cvector<int, sharedmemoryallocator<int>> shmvec; shmvec* vec = ::new(mem.data()) shmvec(sharedmemoryallocator<int>(static_cast<char*>(mem.data()) + sizeof(shmvec), 1024 - sizeof(shmvec))); vec->reserve(100); vec->push_back(100); vec->push_back(200); vec->push_back(300); std::cout<<"address: "<<mem.data()<<"\n"; std::cin.get(); shmvec* ptrvec = reinterpret_cast<shmvec*>(mem.data()); std::cout<<(*ptrvec)[0]; vec->~shmvec(); }
i read somewhere std::vector cannot placed in sharedmemory because might tracking of own in current process's address space. decided write own "vector" cheap class.
next, allocate shared memory block , construct container block shown above in "main".
in other program, (main):
int main() { memorymap mem{"local\\test", 5000, std::ios::in}; mem.open(); mem.map(); typedef cvector<int, sharedmemoryallocator<int>> shmvec; std::cout<<"address: "<<mem.data()<<"\n"; shmvec* ptrvec = reinterpret_cast<shmvec*>(mem.data()); std::cout<<(*ptrvec)[0]; }
when both programs map shared memory block @ 0x370000 works. however, if 1 program allocates sharedmemoryblock @ 0x370000 , second @ 0x380000, crashes (the second program crashes trying access container created first).
any ideas why happens? container in shared memory block. why matter address of blocks have exact same?
here problem:
template<typename t, typename allocator = std::allocator<t>> class cvector { private: t* memory; ^^^^^^^^^^^
because in programs shmvector object stored in shared memory, store data members in shared memory. pointer elements (memory
in case) stored in shared memory.
if shared memory segment loaded @ different address, memory
point @ invalid address in memory space of 1 of 2 programs.
maybe simple solution: don't put shmvec object in shared memory, elements.
Comments
Post a Comment