6

我需要在进程之间共享一堆字符串(将来可能会更复杂的对象)。我决定使用 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我还应该注意,事情在一定程度上起作用。writer 进程可以在 reader 中断之前推送几个小字符串(或一个非常大的字符串)。阅读器以 m_stack->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;
4

2 回答 2

4

关于您的实施,有几件事让我大吃一惊。一种是使用指向命名互斥对象的指针,而大多数 boost 库的文档倾向于向后弯曲而不使用指针。这导致我要求参考您在构建自己的测试用例时使用的程序片段,因为我也遇到过类似的不幸事件,有时唯一的出路是回到示例并一次向前推进一步,直到我遇到了重大变化。

另一件似乎有问题的事情是您为共享内存分配了一个 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. chunks, it won't take long to overflow that stack. That would be my first guess as to why things are haywire.

P.S. I just returned from fixing my name to something resembling my actual identity. 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.)

于 2009-07-13T18:55:00.687 回答
-3

好吧,也许共享内存不是解决您的问题的正确设计。但是我们不知道,因为我们不知道您首先要达到什么目标。

于 2009-04-23T23:27:55.413 回答