简体   繁体   English

增强,共享内存和向量

[英]Boost, Shared Memory and Vectors

I need to share a stack of strings between processes (possibly more complex objects in the future). 我需要在进程之间共享一堆字符串(将来可能会有更复杂的对象)。 I've decided to use boost::interprocess but I can't get it to work. 我决定使用boost :: interprocess但我无法使用它。 I'm sure it's because I'm not understanding something. 我确定这是因为我不理解某些事情。 I followed their example, but I would really appreciate it if someone with experience with using that library can have a look at my code and tell me what's wrong. 我按照他们的例子,但如果有经验使用该库的人可以查看我的代码并告诉我什么是错的,我将非常感激。 The problem is it seems to work but after a few iterations I get all kinds of exceptions both on the reader process and sometimes on the writer process. 问题是它似乎有效,但经过几次迭代后,我在阅读器进程和有时在编写器进程上都会遇到各种异常。 Here's a simplified version of my implementation: 这是我的实现的简化版本:

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 Edited to use named_mutex. 编辑编辑使用named_mutex。 Original code was using interprocess_mutex which is incorrect, but that wasn't the problem. 原始代码使用的是interprocess_mutex,这是不正确的,但这不是问题。

EDIT2 I should also note that things work up to a point. EDIT2我还应该注意到事情在某种程度上是可行的。 The writer process can push several small strings (or one very large string) before the reader breaks. 编写器进程可以在读取器中断之前推送几个小字符串(或一个非常大的字符串)。 The reader breaks in a way that the line m_stack->begin() does not refer to a valid string. 读者打破了m_stack-> begin()行不引用有效字符串的方式。 It's garbage. 这是垃圾。 And then further execution throws an exception. 然后进一步执行抛出异常。

EDIT3 I have modified the class to use boost::interprocess::string rather than std::string. EDIT3我修改了类以使用boost :: interprocess :: string而不是std :: string。 Still the reader fails with invalid memory address. 读者仍然因无效的内存地址而失败。 Here is the reader/writer 这是读者/作者

//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;

There are several things that leaped out at me about your implementation. 关于您的实施,我有几件事情在我身上跳了出来。 One was the use of a pointer to the named mutex object, whereas the documentation of most boost libraries tends to bend over backwards to not use a pointer. 一种是使用指向指定互斥对象的指针,而大多数boost库的文档往往会向后弯曲而不使用指针。 This leads me to ask for a reference to the program snippet you worked from in building your own test case, as I have had similar misadventures and sometimes the only way out was to go back to the exemplar and work forward one step at a time until I come across the breaking change. 这导致我要求参考你在构建自己的测试用例时所使用的程序片段,因为我遇到了类似的错误,有时唯一的出路是回到示例并一步一步向前迈进,直到我遇到了突破性的变化。

The other thing that seems questionable is your allocation of a 65k block for shared memory, and then in your test code, looping to 1000000000, pushing a string onto your stack each iteration. 另一件似乎值得怀疑的事情是你为共享内存分配65k块,然后在你的测试代码中循环到1000000000,每次迭代都将一个字符串推入你的堆栈。

With a modern PC able to execute 1000 instructions per microsecond and more, and operating systems like Windows still doling out execution quanta in 15 millisecond. 现代PC能够每微秒执行1000条指令,而Windows等操作系统仍然可以在15毫秒内完成执行量程。 chunks, it won't take long to overflow that stack. 块,溢出堆栈不会花费很长时间。 That would be my first guess as to why things are haywire. 这将是我的第一个猜测,为什么事情是乱七八糟的。

PS I just returned from fixing my name to something resembling my actual identity. PS我刚从修改我的名字回到类似于我的实际身份的东西。 Then the irony hit that my answer to your question has been staring us both in the face from the upper left hand corner of the browser page! 然后讽刺的是,我对你的问题的回答一直盯着我们从浏览器页面的左上角看到的! (That is, of course, presuming I was correct, which is so often not the case in this biz.) (当然,假设我是正确的,这在这个商业中往往不是这样。)

Well maybe shared memory is not the right design for your problem to begin with. 好吧,共享内存可能不适合您的问题。 However we would not know, because we don't know what you try to achieve in the first place. 但是我们不知道,因为我们首先不知道你想要实现什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM