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また、物事はある程度まで機能することに注意する必要があります。ライター プロセスは、リーダーが中断する前に、いくつかの小さな文字列 (または 1 つの非常に大きな文字列) をプッシュできます。行 m_stack->begin() が有効な文字列を参照していないという方法で、リーダーが中断します。ゴミです。そして、さらに実行すると例外がスローされます。

EDIT3 std::stringではなくboost::interprocess::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;
4

2 に答える 2

4

あなたの実装について私に飛び出したことがいくつかあります。1 つは、名前付きミューテックス オブジェクトへのポインターの使用でしたが、ほとんどのブースト ライブラリのドキュメントは、ポインターを使用しないように後ろ向きに曲がる傾向があります。これにより、独自のテストケースを作成する際に使用したプログラムスニペットへの参照を求めるようになります.私は破壊的な変化に出くわします。

疑わしいと思われるもう 1 つの点は、共有メモリ用に 65k ブロックを割り当ててから、テスト コードで 1000000000 にループし、反復ごとに文字列をスタックにプッシュすることです。

最新の PC は 1 マイクロ秒あたり 1000 以上の命令を実行でき、Windows などのオペレーティング システムは依然として 15 ミリ秒で実行量を処理しています。スタックがオーバーフローするのにそれほど時間はかかりません。それが、なぜ物事が混乱しているのかについての私の最初の推測です。

PS 私は自分の名前を私の実際のアイデンティティに似たものに固定することから戻ってきました. それから皮肉なことに、あなたの質問に対する私の答えが、ブラウザー ページの左上隅から私たちの顔を見つめています。(もちろん、これは私が正しかったと仮定した場合ですが、この業界ではそうではないことがよくあります。)

于 2009-07-13T18:55:00.687 に答える
-3

そもそも、共有メモリは問題の適切な設計ではない可能性があります。ただし、そもそも何を達成しようとしているのかがわからないため、わかりません。

于 2009-04-23T23:27:55.413 に答える