Search code examples
c++boostshared-memoryboost-interprocess

Create a shared-memory vector of strings


I am trying to create a class managing a shared-memory vector of (std)strings.

typedef boost::interprocess::allocator<std::string, boost::interprocess::managed_shared_memory::segment_manager> shmem_allocator;
typedef boost::interprocess::vector<std::string, shmem_allocator> shmem_vector;

shmem_mgr::shmem_mgr() :
    shmem_(create_only, SHMEM_KEY, SHMEM_SIZE),
    allocator_(shmem_.get_segment_manager())
{
    mutex_  = shmem_.find_or_construct<interprocess_mutex>(SHMEM_MUTEX)();
    condition_ = shmem_.find_or_construct<interprocess_condition>(SHMEM_CONDITION)();
    //buffer_ is of type shmem_vector
    buffer_  = shmem_.construct<shmem_vector>(SHMEM_BUFFER_KEY)(allocator_);
}

void shmem_mgr::run() {
    running_ = true;

    while(running_) {
        scoped_lock<interprocess_mutex> lock ( *mutex_ );

        int size = buffer_->size();

        log_.debug() << size << " queued request(s) found" << std::endl; //LINE 27
        for(int i=0; i<size; i++) {
            log_.debug() << buffer_->at(i); // at() crashes my app
        }

        buffer_->clear(); //so does clear()
        condition_->wait (lock);
    }
}

The client successfully adds a string to the vector (it also succeeds to read that string from the buffer for debug), the manager (code above) receives the signal (condtion variable), writes that there is a string in the vector (line 27), but when it tries to get that string via at() the application crashes.


Edit: I've figured out, that the use of std::string is not possible, there is a string container in boost ipc just for this case. This doesn't change the fact that I need a vector of (boost/std) strings...


Q: How can I pass strings across shared memory? I need to store them in some buffer (capable of storing >1 at a time) in shmem, and then fetch in second process - that's the requirement. The input is always std::string and so is the output, but the internal representation in shmem may be different.


Solution

  • From the docs.

    #include <boost/interprocess/managed_shared_memory.hpp>
    #include <boost/interprocess/containers/vector.hpp>
    #include <boost/interprocess/containers/string.hpp>
    #include <boost/interprocess/allocators/allocator.hpp>
    
    int main ()
    {
       using namespace boost::interprocess;
       //Typedefs
       typedef allocator<char, managed_shared_memory::segment_manager>
          CharAllocator;
       typedef basic_string<char, std::char_traits<char>, CharAllocator>
          MyShmString;
       typedef allocator<MyShmString, managed_shared_memory::segment_manager>
          StringAllocator;
       typedef vector<MyShmString, StringAllocator>
          MyShmStringVector;
    
       //Open shared memory
       //Remove shared memory on construction and destruction
       struct shm_remove
       {
          shm_remove() { shared_memory_object::remove("MySharedMemory"); }
          ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
       } remover;
    
       managed_shared_memory shm(create_only, "MySharedMemory", 10000);
    
       //Create allocators
       CharAllocator     charallocator  (shm.get_segment_manager());
       StringAllocator   stringallocator(shm.get_segment_manager());
    
       //This string is in only in this process (the pointer pointing to the
       //buffer that will hold the text is not in shared memory).
       //But the buffer that will hold "this is my text" is allocated from
       //shared memory
       MyShmString mystring(charallocator);
       mystring = "this is my text";
    
       //This vector is only in this process (the pointer pointing to the
       //buffer that will hold the MyShmString-s is not in shared memory).
       //But the buffer that will hold 10 MyShmString-s is allocated from
       //shared memory using StringAllocator. Since strings use a shared
       //memory allocator (CharAllocator) the 10 buffers that hold
       //"this is my text" text are also in shared memory.
       MyShmStringVector myvector(stringallocator);
       myvector.insert(myvector.begin(), 10, mystring);
    
       //This vector is fully constructed in shared memory. All pointers
       //buffers are constructed in the same shared memory segment
       //This vector can be safely accessed from other processes.
       MyShmStringVector *myshmvector =
          shm.construct<MyShmStringVector>("myshmvector")(stringallocator);
       myshmvector->insert(myshmvector->begin(), 10, mystring);
    
       //Destroy vector. This will free all strings that the vector contains
       shm.destroy_ptr(myshmvector);
       return 0;
    }