2017-07-05 11 views
1

私は、ブーストの例に基づいて、共有メモリのスレッドセーフ待ち行列クラスを実装しました。シンプルなプロデューサ/コンシューマモデルでは期待通りに動作します。共有メモリにアクセスするときの読み取りアクセス違反

IConcurrentIPCQueueは、ConcurrentIPCQueueクラスで実装されているインターフェイスを定義しました。私は別の問題のためのキューにアダプタを実装することができるようにインターフェイスが必要です。

私の最初のバージョンと以下の現在の唯一の違いは以下の通りです:

最初のバージョン:

template <class T> class ConcurrentIPCQueue 

は今、私はこのようなインターフェイスを実装すること、情報を追加:

現在のバージョン:

`template <class T> class ConcurrentIPCQueue :public IConcurrentIPCQueue<T>` 

は、コンシューマ側の読み取りアクセス違反になります。プロデューサー側では、私は容易にpush_backpop_frontのデータを単独で正しく扱うことができます。しかし、不思議なことに消費者側では、私は共有メモリにアクセスすることはできません(segment.findからのペアは正しくアドレスと1を返します)。 それでは、インターフェイスを実装しているバージョンが消費者側に違いをもたらし、この奇妙なエラーが発生するのはなぜですか?そして私はそれをどのように解決することができますか?

短い例を維持するために、私はここで、キューのミニマルモデルを提示:

#include <boost/interprocess/allocators/allocator.hpp> 
#include <boost/interprocess/containers/deque.hpp> 
#include <boost/interprocess/managed_shared_memory.hpp> 
#include <boost/interprocess/sync/interprocess_condition.hpp> 
#include <boost/interprocess/sync/interprocess_mutex.hpp> 
#include <boost/thread/lock_guard.hpp> 
#include <sstream> 

namespace boost_ipc = boost::interprocess; 
static char const *SHMEMNAME= "SHMEM"; 
static char const *SHQUEUENAME= "MYQUEUE"; 

template <class T> class IConcurrentIPCQueue 
{ 
public: 
    virtual void push_back(T const & data) = 0; 
    virtual bool pop_front(T & data) = 0; 
virtual unsigned int size() = 0; 
}; 

template <class T> class ConcurrentIPCQueue :public IConcurrentIPCQueue<T> 
{ 
public: 
    // allocator for allocating memory from the shared memory 
    typedef boost_ipc::allocator<T, boost_ipc::managed_shared_memory::segment_manager> ShmemAlloc; 
    typedef boost_ipc::interprocess_mutex IPC_Mutex; 
    typedef boost_ipc::interprocess_condition IPC_Cond; 
    typedef boost::lock_guard<IPC_Mutex> LockGuard; 

    ConcurrentIPCQueue(ShmemAlloc salloc) : mQueue_(salloc) { } 

    void push_back(T const & data) 
    { 
     { 
      LockGuard lock(mMutex_); 
      mQueue_.push_back(data); 
     } 
     mWait_.notify_one(); 
    } 

    bool pop_front(T & data) 
    { 
     LockGuard lock(mMutex_); 

     if (mQueue_.empty()) 
      return false; 

     data = mQueue_.front(); // return reference to first element 
     mQueue_.pop_front(); // remove the first element 

     return true; 
    } 

unsigned int size() 
{ 
    LockGuard lock(mMutex_); 
    return mQueue_.size(); 
} 

private: 
    boost_ipc::deque<T, ShmemAlloc> mQueue_; 
    IPC_Mutex mMutex_; 
    IPC_Cond mWait_; 
}; 

typedef ConcurrentIPCQueue<char> myqueue; 

void consumer() 
{ 
    boost_ipc::managed_shared_memory openedSegment(boost_ipc::open_only, SHMEMNAME); 

    myqueue*openedQueue = openedSegment.find<myqueue>(SHQUEUENAME).first; 
    char tmp; 

    while (openedQueue->pop_front(tmp)) { 
     std::cout << "Received " << tmp << "\n"; 
    } 
} 

void producer() { 
    boost_ipc::shared_memory_object::remove(SHMEMNAME); 

    boost_ipc::managed_shared_memory mysegment(boost_ipc::create_only, SHMEMNAME, 131072); 

    myqueue::ShmemAlloc alloc(mysegment.get_segment_manager()); 
    myqueue*myQueue = mysegment.construct<myqueue>(SHQUEUENAME)(alloc); 
char mychar='A'; 

    for (int i = 0; i < 10; ++i) 
     myQueue->push_back(mychar); 

    while (myQueue->size() > 0) 
     continue; 
} 

int main() 
{ 
    //producer(); // delete comment for creating producer process 
    consumer(); 
    return 0; 
} 
+0

は、なぜあなたはあなたの文字列定数は二回定義されていますか?完全な実行可能プログラムを提供できますか? – didierc

+0

これはミニマルモデルを作成するときの間違いでした。私はそれを削除し、main-function()を追加して、プロデューサ()またはコンシューマ( –

答えて

1

はUPDATE:

私はMSVC15.3でそれを再現し、1.64を高めることができます。

vtableポインタが問題であることが判明しました。実行時の多態型(std::is_polymorphic<T>)を持つとすぐに未定義の動作につながる、各プロセスでは異なります。

結局のところドキュメントは明確に禁じ:Is it possible to store polymorphic class in shared memory?

+0

)のいずれかの機能にコメントする必要があります。どうして私はインターフェースから継承した時とそうでない時に違いが出るのですか?私はVSで手作業でスタックとヒープサイズ、ウィンドウ上の最初の仮想メモリサイズを増加させ、コードのような "予約"サイズを増加させたが、それでも(私はインターフェイスから継承しない限り)動作しません。多分別の問題かもしれませんか? –

+0

コードサンプルで問題が示されていることを確認してください。今、私はあなたが「私はインターフェースから継承しない」という意味を知りません。 – sehe

+0

私は問題をよりよく説明しようとしましたが、今はうまくいきません。 –

関連する問題