Reputation: 20658
I'm aware of the boost interprocess containers, and the examples use managed shared memory. But I want to use a simple boost::interprocess::shared_memory_object
which has an object inside it, and either a vector or any other container inside that object. That just doesn't seem to work.
Tried this:
#include <stack>
#include <boost/interprocess/containers/vector.hpp>
namespace bip = boost::interprocess;
class SharedMemoryMetadata
{
public:
std::stack<unsigned short> newData;
int deleteme;
bip::vector<unsigned short> v;
};
and create the shared memory with:
bip::shared_memory_object::remove(OUTPUT_METADATA_MEMORY_SEGMENT_NAME);
sharedMemoryMetadataForOutput = new bip::shared_memory_object(bip::create_only, OUTPUT_METADATA_MEMORY_SEGMENT_NAME, bip::read_write);//use old shared memory if exists else create a new one
sharedMemoryMetadataForOutput->truncate(sizeof(SharedMemoryMetadata)+ (3*sizeof(unsigned int)*MAX_NUMBER_OF_OBJECTS_EXPECTED_TO_BE_IN_SHARED_MEMORY));//set the size of the memory object
sharedMemoryMetadataRegion = new bip::mapped_region(*sharedMemoryMetadataForOutput, bip::read_write);//map the whole shared memory in this process
void* sharedMemorySegmentForMetadataStorage = sharedMemoryMetadataRegion->get_address();//get the region address
sharedMemoryMetadataObject = new (sharedMemorySegmentForMetadataStorage) SharedMemoryMetadata();//create a shared memory buffer in memory
and I try to access it with:
bip::shared_memory_object* sharedMemoryMetadataForOutput;
SharedMemoryMetadata* sharedMemoryMetadataObject;
bip::mapped_region* sharedMemoryMetadataRegion;
bip::shared_memory_object* sharedMemoryMetadataForOutput;
SharedMemoryMetadata* sharedMemoryMetadataObject;
bip::mapped_region* sharedMemoryMetadataRegion;
sharedMemoryMetadataForOutput = new bip::shared_memory_object(bip::open_only, OUTPUT_METADATA_MEMORY_SEGMENT_NAME, bip::read_write);//create a shared memory object http://blog.wolfgang-vogl.com/?p=528
sharedMemoryMetadataRegion = new bip::mapped_region(*sharedMemoryMetadataForOutput, bip::read_write);//Map the whole shared memory in this process
void * sharedMemorySegmentForMetadataStorage = sharedMemoryMetadataRegion->get_address();//get the region address
sharedMemoryMetadataObject = static_cast<SharedMemoryMetadata*>(sharedMemorySegmentForMetadataStorage);//Obtain the shared structure
as expected, std::stack<unsigned short> newData;
turns out to be empty even if something is written to the stack. But if I assign a value to int deleteme
, I'm able to read it from another program that accesses shared memory.
push_back
to bip::vector<unsigned short> v;
works, but when I try to access it from the other program, I get a segmentation fault. Is there a way I can store and access a vector in shared_memory_object
or is using managed shared memory then only way? Even if I use managed shared memory, how can I store the vectors inside the SharedMemoryMetadata
class as shown above?
Upvotes: 2
Views: 354
Reputation: 16156
I'll explain with the vector as example. Basically, a std::vector
is something like this:
template<typename T>
struct vec {
std::size_t size;
T * data;
};
When you put this into any shared memory, what you share is essentially a size and a pointer.
When you add elements to the vector, it's asking its allocator for memory to store them to. In your example this is the default allocator std::allocator
which in turn calls operator new
.
Thus the vector gets memory from the non shared heap memory to store its elements to. Thus, the (shared) pointer to this (non shared) memory will be invalid in the other address space, causing undefined behaviour.
To solve this you either need a vector that is aware of being shared (or designed for that) or you write yourself an own allocator that is allocating from shared memory, and use that with the STL classes.
Upvotes: 1