I’m trying to create a wrapper class to control a managed shared memory segment using Boost::Interprocess. I’m having trouble reading data from the shared memory vector of strings…….
When the vector is instantiated in the managed shared segment I place in the first vector element a test string; “testing testing 1 2 3”. Immediately after placing it there and in the scope of the same code block I can access the vector element and print out the string using std::cout.
However when I try to read the vector element using the read() function the test program crashes. The problem is with the line:
std::string stdStr = sharedSegmentVector->at(index).c_str();
Question is how to fix this? I’m confused because at instantiation time this same code will access the shared memory vector; later on in the read() function it will not.
I’ve as yet been unable to test the write() function; because I can’t yet read() the vector!
Any help to get this working is much appreciated,
With thanks,
Riskybiz
Class Definition:
#ifndef SHARED_MEMORY_WRAPPER_H//if not defined already
#define SHARED_MEMORY_WRAPPER_H//then define it
#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>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <iostream>
#include <stdexcept>
using namespace boost::interprocess;
class SharedMemoryWrapper
{
public:
SharedMemoryWrapper(const std::string &name, bool server) : m_name(name), m_server(server)
{
if (server)
{
named_mutex::remove("named_mutex");
shared_memory_object::remove(m_name.c_str());
//Create shared memory
managed_shared_memory m_segment(create_only, m_name.c_str(), 10000);
//Create allocators
CharAllocator charallocator(m_segment.get_segment_manager());
StringAllocator stringallocator(m_segment.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 = "testing testing 1 2 3";
//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 *sharedSegmentVector = m_segment.construct<MyShmStringVector>("sharedSegmentVector")(stringallocator);
sharedSegmentVector->push_back(mystring);
std::string outStr = sharedSegmentVector->at(0).c_str();
std::cout << "Shared Memory Vector Instantiated: Index 0 Data is: " << outStr << std::endl;
}
else
{
//Open the shared segment
managed_shared_memory m_segment(open_only, name.c_str());
//Find the vector using the c-string name and open it
MyShmStringVector *sharedSegmentVector = m_segment.find<MyShmStringVector>("sharedSegmentVector").first;
}
m_mutex = new named_mutex(open_or_create, "named_mutex");
}
~SharedMemoryWrapper()
{
if (m_server)
{
named_mutex::remove("named_mutex");
//Destroy the vector from the managed_shared_memory
//m_segment->destroy_ptr(sharedSegmentVector);//This will free all strings that the vector contains
m_segment->destroy<MyShmStringVector>("sharedSegmentVector");//Destroy the vector
//Is it necessary to destroy the allocators here?
//Remove the managed_shared_memory; this may fail if the memory does not exist or is mapped or opened by another process
shared_memory_object::remove(m_name.c_str());
}
delete m_mutex;
delete m_segment;
}
//Writer
void write(const std::string &in)
{
try
{
CharAllocator charallocator(m_segment->get_segment_manager());
scoped_lock<named_mutex> lock(*m_mutex);
MyShmString shmStr(in.c_str(), charallocator);
sharedSegmentVector->push_back(shmStr);
}
catch(...)
{
std::cout << "Error in SharedMemoryWrapper::write(): unknown error" << std::endl;
}
}
//Reader
std::string read(int index)
{
try
{
scoped_lock<named_mutex> lock(*m_mutex);
std::cout << "Shared Memory Vector Entered Read(), Passed Index: " << index << std::endl;
std::string stdStr = sharedSegmentVector->at(index).c_str();
std::cout << "Shared Memory Vector Read At: Index" << index << "Data is: " << stdStr << std::endl;
return stdStr;
}
catch(std::range_error err)
{
std::cout << "Error in SharedMemoryWrapper::read(): range_error" << std::endl;
}
catch(...)
{
std::cout << "Error in SharedMemoryWrapper::read(): unknown error " << std::endl;
}
return "ERROR IN SharedMemoryWrapper::read()";
}
private:
//Typedefs
typedef boost::interprocess::allocator<char, managed_shared_memory::segment_manager> CharAllocator;
typedef boost::interprocess::basic_string<char, std::char_traits<char>, CharAllocator> MyShmString;
typedef boost::interprocess::allocator<MyShmString, managed_shared_memory::segment_manager> StringAllocator;
typedef boost::interprocess::vector<MyShmString, StringAllocator> MyShmStringVector;
bool m_server;
std::string m_name;
managed_shared_memory *m_segment;
MyShmStringVector *sharedSegmentVector;
named_mutex *m_mutex;
};//class
#endif//header guard
Test Programme:
#include "stdafx.h"
#include "SharedMemoryWrapper.h"
#include <iostream>
#include <string>
int main(int argc, char *argv[])
{
SharedMemoryWrapper *smw = new SharedMemoryWrapper("SharedMemory1", true);
std::string outStr = smw->read(0);
std::cout << outStr << std::endl;
return 0;
}