簡體   English   中英

增強,共享內存和向量

[英]Boost, Shared Memory and Vectors

我需要在進程之間共享一堆字符串(將來可能會有更復雜的對象)。 我決定使用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塊,然后在你的測試代碼中循環到1000000000,每次迭代都將一個字符串推入你的堆棧。

現代PC能夠每微秒執行1000條指令,而Windows等操作系統仍然可以在15毫秒內完成執行量程。 塊,溢出堆棧不會花費很長時間。 這將是我的第一個猜測,為什么事情是亂七八糟的。

PS我剛從修改我的名字回到類似於我的實際身份的東西。 然后諷刺的是,我對你的問題的回答一直盯着我們從瀏覽器頁面的左上角看到的! (當然,假設我是正確的,這在這個商業中往往不是這樣。)

好吧,共享內存可能不適合您的問題。 但是我們不知道,因為我們首先不知道你想要實現什么。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM