升压,共享内存和载体 [英] Boost, Shared Memory and Vectors

查看:107
本文介绍了升压,共享内存和载体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要共享串的过程之间的堆叠(在未来可能更复杂的对象)。我决定使用boost ::进程间,但我无法得到它的工作。我敢肯定,这是因为我不理解的东西。我跟着他们为榜样,但我真的AP preciate,如果有人与使用该库可以看看我的code,告诉我什么是错的经验。问题是,它似乎工作,但几次迭代后,我得到各种既对读者进程,有时在写进程异常。下面是我实现的一个简化版本:

 使用空间boost ::进程间;
类SharedMemoryWrapper
{
上市:
    SharedMemoryWrapper(常量标准::字符串&放大器;名称,布尔服务器):
      m_name(名称),
      m_server(服务器)
    {
        如果(服务器)
        {
            named_mutex ::删除(named_mutex);
            shared_memory_object ::删除(m_name.c_str());
            m_segment =新managed_shared_memory(create_only,name.c_str(),65536);
            m_stackAllocator =新StringStackAllocator(m_segment-> get_segment_manager());
            m_stack = m_segment->构建< StringStack>(MyStack)(* m_stackAllocator);
        }
        其他
        {
            m_segment =新managed_shared_memory(open_only,name.c_str());
            m_stack = m_segment->找到< StringStack方式>(MyStack)第一;
        }
        m_mutex =新named_mutex(open_or_createnamed_mutex);
    }    〜SharedMemoryWrapper()
    {
        如果(m_server)
        {
            named_mutex ::删除(named_mutex);
            m_segment->&毁灭LT; StringStack>(MyStack);
            删除m_stackAllocator;
            shared_memory_object ::删除(m_name.c_str());
        }
        删除m_mutex;
        删除m_segment;
    }    无效的push(常量标准::字符串&安培;中)
    {
        scoped_lock的< named_mutex>锁定(* m_mutex);
        提高::进程间::字符串INSTR(in.c_str());
        m_stack->的push_back(INSTR);
    }
    标准::字符串POP()
    {
        scoped_lock的< named_mutex>锁定(* m_mutex);
        性病::字符串结果=;
        如果(m_stack->尺寸()大于0)
        {
            结果=标准::字符串(m_stack->开始() - GT; c_str());
            m_stack->删除(m_stack->开始());
        }
        返回结果;
    }
私人的:
    TYPEDEF的boost ::进程间::分配器<的boost ::进程间::字符串,提高::进程间:: managed_shared_memory :: segment_manager> StringStackAllocator;
    TYPEDEF的boost ::进程间::矢量<升压::进程间::字符串,StringStackAllocator> StringStack;
    布尔m_server;
    标准::字符串m_name;
    提高::进程间:: managed_shared_memory * m_segment;
    StringStackAllocator * m_stackAllocator;
    StringStack * m_stack;
    提高::进程间:: named_mutex * m_mutex;
};

修改的编辑使用named_mutex。原来的code,采用interprocess_mutex这是不正确,但是这不是问题。

EDIT2 的我应该也注意到事情的工作到一个点。笔者过程可以在读写休息前推几个小串(或一个非常大的字符串)。在某种程度上,该行m_stack->开始,读者符()不引用有效的字符串。这是垃圾。然后再执行会抛出异常。

EDIT3 的我已经修改了使用boost ::进程间::字符串,而不是标准::字符串的类。尽管如此读者失败,无效的内存地址。这里是读/写器

  //读取器进程
SharedMemoryWrapper MEM(存储器我,真正的);
标准::字符串的myString;
INT X = 5;

{
    myString的= mem.pop();
    如果(的myString!=)
    {
        性病::法院LT&;< MyString的<<的std :: ENDL;
    }
}而(1); //而(MyString的=!);//作家
SharedMemoryWrapper MEM(存储器我,FALSE);
的for(int i = 0; I< 10亿;我++)
{
    的std :: stringstream的SS;
    SS<<一世; //几千次迭代后会导致失败
    // SS<< AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA<<一世; //导致立即失败
    mem.push(ss.str());
}
返回0;


解决方案

有几件事情,我跳出了关于您的实现。一个是使用指针命名的互斥体对象,而大多数Boost库的文档,往往使出浑身解数为不使用指针。这使我问到片段您在构建自己的测试案例工作方案的参考,因为我有过类似的不幸的事,有时甚至是唯一的出路是回到典范,并在同一时间,直到工作向前一步我遇到了重大更改。

这似乎值得商榷的另一件事是你的一个65000块共享内存分配,然后在您的测试code,循环1000000000,推串到你的栈每一次迭代。

随着现代计算机能够执行每微秒多1000条指令,并且操作系统,如Windows仍然在15毫秒少量发放执行量子。块,它不会需要很长时间溢出的堆栈。这将是我的第一个猜测,为什么事情失控。

P.S。
我只是从我的名字固定在类似的东西我的真实身份返回。然后,具有讽刺意味的​​打我​​的回答对你的问题一直盯着我们两个的脸从浏览器页面的左上角! (那是当然,presuming我是正确的,这是常常不在此BIZ的情况下)。

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. 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. Original code was using interprocess_mutex which is incorrect, but that wasn't the problem.

EDIT2 I should also note that things work up to a point. 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. 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. 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. 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.

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.)

这篇关于升压,共享内存和载体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆