3

I've read that stl vector does not work well with SYS V shared memory. But if I use POSIX shm_open and then mmap with NULL (mmap(NULL, LARGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0) and give a much larger size than my object, which contains my vector, and after mapping add aditional items to the vector, can there be a problem other than exceeding the LARGE_SIZE space? Other related question: is it guaranteed on a recent SUSE linux that when mapped to the same start address (using above syntax) in unrelated processes my object will be mapped directly and no (system) copy is performed to actualize changed values in the processes (like what happens with normal open and normal files when mmap-ed)? Thanks!

Edit: Is this correct then?:

void* mem = allocate_memory_with_mmap(); // say from a shared region
MyType* ptr = new ( mem ) MyType( args );
ptr.~MyType() //is this really needed?

now in an unrelated process:

MyType* myptr = (MyType*)fetch_address_from_mmap(...)
myptr->printHelloWorld();
myptr->myvalue = 1; //writes to shared memory
myptr.~MyType() //is this really needed?

now if I want to free memory

munmap(address...) //but this done only once, when none of the processes use it any more
user1132655
  • 243
  • 4
  • 14

1 Answers1

4

You are missing the fact that the STL vector is usually just a tuple of (mem pointer, mem size, element count), where actual memory for contained objects is received from the allocator template parameter.

Placing an instance of std::vector in shared memory does not make any sense. You probably want to check out boost::interprocess library instead.

Edit 0:

Memory allocation and object construction are two distinct phased, though combined in a single statement like bellow (unless operator new is re-defined for MyType):

// allocates from process heap and constructs
MyType* ptr = new MyType( args );

You can split these two phases with placement new:

void* mem = allocate_memory_somehow(); // say from a shared region
MyType* ptr = new ( mem ) MyType( args );

Though now you will have to explicitly call the destructor and release the memory:

ptr->~MyType();
release_memory_back_to_where_it_came_from( ptr );

This is essentially how you can construct objects in shared memory in C++. Note though that types that store pointers are not suitable for shared memory since any pointer in one process memory space does not make any sense in the other. Use explicit sizes and offsets instead.

Hope this helps.

Community
  • 1
  • 1
Nikolai Fetissov
  • 82,306
  • 11
  • 110
  • 171
  • Maybe i'm missing some basic understanding... could you tell me, that if I bind a pointer via mmap (MyPointer* a). And then say a = new MyPointer(). Where will the object be allocated. In the shared memory or the process space? If in the process space, then what will happen if an other process tries to use it? – user1132655 Sep 26 '12 at 14:49
  • Oh I see, so "plain old" new will put the object in the processes private heap and not copy it to the shared memory? But why do I need to delete it this way? Cant I just giva mem a type via casting (MyType*) and then use delete operator on mem (delete mem)? – user1132655 Sep 26 '12 at 15:46
  • Ok, I think I see delete operator wouldnt make too much sense. But what do you mean by where it came from? Regarding the release I would have to use munmap (which frees the POSIX object from shm). Why do I need to put it back somewhere? Also I hope I can cast mem to MyType class, otherwise how could I use it's non-pointer member variables and member functions in an unrelated process. Manually calling the destructor is not very clear, why is that important. – user1132655 Sep 26 '12 at 15:58
  • Basically, you need a "master" process creating shared memory and populating data structures in it (here you can use constructors as above, or just do PODs for simplicity), and then "slave" processes would map that memory and cast to proper types. – Nikolai Fetissov Sep 26 '12 at 17:25