Necesito compartir una pila de cadenas entre procesos (posiblemente objetos más complejos en el futuro). Decidí usar boost :: interprocess pero no puedo hacer que funcione. Estoy seguro de que es porque no estoy entendiendo algo. Seguí su ejemplo, pero realmente agradecería que alguien con experiencia en el uso de esa biblioteca pueda echar un vistazo a mi código y decirme qué sucede. El problema es que parece funcionar, pero después de algunas iteraciones recibo todo tipo de excepciones tanto en el proceso de lectura como en el proceso de escritura. Aquí hay una versión simplificada de mi aplicación:Boost, memoria compartida y vectores
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());
m_segment = new managed_shared_memory (create_only,name.c_str(),65536);
m_stackAllocator = new StringStackAllocator(m_segment->get_segment_manager());
m_stack = m_segment->construct<StringStack>("MyStack")(*m_stackAllocator);
}
else
{
m_segment = new managed_shared_memory(open_only ,name.c_str());
m_stack = m_segment->find<StringStack>("MyStack").first;
}
m_mutex = new named_mutex(open_or_create, "named_mutex");
}
~SharedMemoryWrapper()
{
if (m_server)
{
named_mutex::remove("named_mutex");
m_segment->destroy<StringStack>("MyStack");
delete m_stackAllocator;
shared_memory_object::remove(m_name.c_str());
}
delete m_mutex;
delete m_segment;
}
void push(const std::string & in)
{
scoped_lock<named_mutex> lock(*m_mutex);
boost::interprocess::string inStr(in.c_str());
m_stack->push_back(inStr);
}
std::string pop()
{
scoped_lock<named_mutex> lock(*m_mutex);
std::string result = "";
if (m_stack->size() > 0)
{
result = std::string(m_stack->begin()->c_str());
m_stack->erase(m_stack->begin());
}
return result;
}
private:
typedef boost::interprocess::allocator<boost::interprocess::string, boost::interprocess::managed_shared_memory::segment_manager> StringStackAllocator;
typedef boost::interprocess::vector<boost::interprocess::string, StringStackAllocator> StringStack;
bool m_server;
std::string m_name;
boost::interprocess::managed_shared_memory * m_segment;
StringStackAllocator * m_stackAllocator;
StringStack * m_stack;
boost::interprocess::named_mutex * m_mutex;
};
EDITAR editado para usar named_mutex. El código original estaba usando interprocess_mutex que es incorrecto, pero ese no era el problema.
EDIT2 Debo señalar también que las cosas funcionan hasta cierto punto. El proceso de escritura puede empujar varias cadenas pequeñas (o una cadena muy grande) antes de que el lector se rompa. El lector se rompe de forma que la línea m_stack-> begin() no se refiere a una cadena válida. Es basura. Y luego la ejecución adicional arroja una excepción.
EDIT3 He modificado la clase para usar boost :: interprocess :: string en lugar de std :: string. Todavía el lector falla con una dirección de memoria no válida. Aquí está el lector/escritor
//reader process
SharedMemoryWrapper mem("MyMemory", true);
std::string myString;
int x = 5;
do
{
myString = mem.pop();
if (myString != "")
{
std::cout << myString << std::endl;
}
} while (1); //while (myString != "");
//writer
SharedMemoryWrapper mem("MyMemory", false);
for (int i = 0; i < 1000000000; i++)
{
std::stringstream ss;
ss << i; //causes failure after few thousand iterations
//ss << "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" << i; //causes immediate failure
mem.push(ss.str());
}
return 0;
Lo siento muchísimo por los carteles anteriores. Hice clic en "eliminar" por error y borré mi publicación original de esta misma pregunta. – Budric
¿No puedes recuperar? ¿O eso solo funciona para las respuestas? –
¿Puedo mordazar el tamaño de sus métodos en línea? ¿O eso me marca como un novato en C++? –