Ho bisogno di condividere una pila di stringhe tra i processi (possibilmente oggetti più complessi in futuro). Ho deciso di usare boost :: interprocess ma non riesco a farlo funzionare. Sono sicuro che è perché non capisco qualcosa. Ho seguito il loro esempio, ma sarei davvero grato se qualcuno con esperienza nell'utilizzo di quella libreria possa dare un'occhiata al mio codice e dirmi cosa c'è che non va. Il problema è che sembra funzionare ma dopo alcune iterazioni ottengo tutti i tipi di eccezioni sia sul processo del lettore che a volte sul processo di scrittura. Ecco una versione semplificata della mia realizzazione:Boost, memoria condivisa e vettori
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;
};
EDIT A cura di utilizzare named_mutex. Il codice originale utilizzava interprocess_mutex che non è corretto, ma non era questo il problema.
EDIT2 Vorrei anche notare che le cose funzionano fino a un certo punto. Il processo di scrittura può spingere diverse stringhe (o una stringa molto grande) prima che il lettore si rompa. Il lettore si spezza in un modo che la riga m_stack-> begin() non fa riferimento a una stringa valida. È spazzatura. E poi l'ulteriore esecuzione genera un'eccezione.
EDIT3 Ho modificato la classe per utilizzare boost :: interprocess :: string piuttosto che std :: string. Ancora il lettore ha esito negativo con indirizzo di memoria non valido. Ecco il lettore/scrittore
//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;
Sono terribilmente dispiaciuto per i poster precedenti. Ho cliccato "cancella" per errore e cancellato il mio post originale di questa stessa identica domanda. – Budric
Non puoi annullare l'operazione? O funziona solo per le risposte? –
Mi è permesso di imbavagliare le dimensioni dei tuoi metodi in linea? O questo mi segna come un noob in C++? –