c++ - Boost、共享内存和 vector

标签 c++ boost ipc interprocess

我需要在进程之间共享一堆字符串(将来可能是更复杂的对象)。我决定使用 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->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;

最佳答案

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

另一件似乎有问题的事情是你为共享内存分配了一个 65k 的 block ,然后在你的测试代码中,循环到 1000000000,每次迭代将一个字符串压入你的堆栈。

现代 PC 能够每微秒执行 1000 条指令甚至更多,而 Windows 等操作系统仍在 15 毫秒内分配执行量子。 block ,很快就会溢出那个堆栈。这将是我对为什么事情失控的第一个猜测。

附言 我刚把我的名字改成与我的真实身份相似的东西回来。然后具有讽刺意味的是,我对您问题的回答一直在浏览器页面的左上角盯着我们俩! (当然,这是假设我是正确的,但在这个行业中通常情况并非如此。)

关于c++ - Boost、共享内存和 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/783623/

相关文章:

c++ - 类型的非常量引用的无效初始化错误

c++ - 如何将数组引用作为参数从程序集传递给 C++ 函数

c++ - boost-libs 构建失败

c++ - boost socket 。格式化/重新安装 ubuntu 后,工作代码不再工作。权限问题?

php - 如何使 PHP 脚本实时响应数据库插入?

c++ - C1001 : An internal error has occurred in the compiler when including <boost/shared_ptr. hpp>

python - 编译 new_op 教程时出错(Tensorflow)

c++ - 函数返回的 boost::multi_array_ref 安全吗?

c - 设计一个具有非阻塞管道转发到另一台服务器的代理

c - 如何多次写入/读取管道