我需要在进程之间共享一堆字符串(将来可能是更复杂的对象)。我决定使用boost :: interprocess但我无法使用它。我确定这是因为我不理解某些事情。我按照他们的例子,但如果有经验使用该库的人可以查看我的代码并告诉我什么是错的,我将非常感激。问题是它似乎有效,但经过几次迭代后,我在阅读器进程和有时在编写器进程上都会遇到各种异常。这是我的实现的简化版本:
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;
};
编辑编辑使用named_mutex。原始代码使用的是interprocess_mutex,这是不正确的,但这不是问题。
EDIT2 我还应该注意到事情在某种程度上是可行的。编写器进程可以在读取器中断之前推送几个小字符串(或一个非常大的字符串)。读者打破了m_stack-&gt; begin()行不引用有效字符串的方式。这是垃圾。然后进一步执行抛出异常。
EDIT3 我修改了类以使用boost :: interprocess :: string而不是std :: string。读者仍然因无效的内存地址而失败。这是读者/作者
//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;
答案 0 :(得分:4)
关于你的实施,有几件事情向我跳了出来。一种是使用指向指定互斥对象的指针,而大多数boost库的文档往往会向后弯曲而不使用指针。这导致我要求参考你在构建自己的测试用例时所使用的程序片段,因为我遇到了类似的错误,有时唯一的出路是回到示例并一步一步向前迈进,直到我遇到了突破性的变化。
另一件值得怀疑的事情是你为共享内存分配65k块,然后在你的测试代码中循环到1000000000,每次迭代都会将一个字符串推入你的堆栈。
现代PC能够每微秒执行1000条指令,而Windows等操作系统仍然可以在15毫秒内完成执行量程。块,溢出堆栈不会花费很长时间。这将是我的第一个猜测,为什么事情是乱七八糟的。
P.S。 我刚从修改我的名字回到类似于我的真实身份的东西。然后讽刺的是,我对你的问题的回答一直盯着我们从浏览器页面的左上角看到的! (当然,假设我是正确的,这在这个商业中往往不是这样。)
答案 1 :(得分:-3)
好吧,共享内存可能不适合您的问题。但是我们不知道,因为我们一开始并不知道你想要达到的目的。