2009-04-23 79 views
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我還應該注意到事情總結到一定程度。編寫器進程可以在閱讀器中斷之前推送幾個小字符串(或一個非常大的字符串)。閱讀器以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; 
+0

我對以前的海報非常抱歉。我點擊了「刪除」,並刪除了我原來的這個完全相同的問題。 – Budric 2009-04-23 21:34:57

+1

你不能取消刪除?或者這隻適用於答案? – 2009-04-23 21:38:16

回答

4

有幾件事情讓我想起你的實現。一種是使用指向名爲mutex對象的指針,而大多數boost庫的文檔往往會向後彎曲而不使用指針。這導致我要求參考您在構建自己的測試用例時所使用的程序片段,因爲我曾經有過類似的不幸事件,有時唯一的出路是回到示例,並一次一步地前進我遇到了突變。

另一件似乎有問題的事情是你爲共享內存分配了一個65k塊,然後在你的測試代碼中,循環到1000000000,每次迭代將一個字符串推入你的棧中。

現代PC能夠執行每微秒和更多1000條指令,而像Windows這樣的操作系統仍然在15毫秒內完成執行量。塊,溢出堆棧不會很長。這將是我第一次猜測爲什麼事情是不合時宜的。

P.S. 我剛剛從修復我的名字返回類似於我的實際身份的東西。然後,諷刺的是,我對你的問題的回答一直在瀏覽器頁面的左上角盯着我們! (當然,假設我是對的,在這個行業中情況往往不是這樣)。

-3

嗯可能共享內存不是你的問題開始的正確設計。但是我們不知道,因爲我們不知道你想要達到什麼目標。