2

共有メモリ セグメントに std::map を格納しようとしています。しかし、私は地図を回復することができません。

(以下のクラスを使用して) 共有メモリ セグメントを作成し、それにマップ アドレスを割り当てます。

しかし、それを回復しようとすると、悪いポインターが表示されます。

以下にいくつかのコード スニペットを示します。

    // This is in my header file
    CSharedMem * shMem;
    // This is in my cpp file - inside my class constructor
    shMem = new CSharedMem("MyShMem", 16536);
    void * ptr = shMem->GetAddress();
    std::map<int,int> myMap;
    ptr = &myMap;
    shMem-ReleaseAddress();

    // This is inside another function
    void * ptr = shMem->GetAdress();

    std::map<int,int> myMap = *static_cast<std::map<int,int> *> (ptr);

誰も手がかりを持っていますか?

CSharedMem クラスのヘッダー ファイル:

    #pragma once

    #include <string>

    class CSharedMem
    {
    public:
    CSharedMem(const std::string& name, std::size_t size);
    ~CSharedMem();

    void* GetAddress() const;
    void ReleaseAddress();
    bool IsShared() const;
    private:
    bool shared_;
    void* address_;

    private:
    void* shm_;
    void* mtx_;
    };

cpp ファイル:

    #include "StdAfx.h"
    #include "SharedMem.h"
    #include <windows.h>
    CSharedMem::CSharedMem(const std::string& name, std::size_t size)
    : shared_(false), 
    address_(NULL)
    {
    shm_ = CreateFileMapping(INVALID_HANDLE_VALUE, 
                            NULL, PAGE_READWRITE, 
                            0, 
                            static_cast<DWORD>(size), 
                            name.c_str() );
    if( shm_ == INVALID_HANDLE_VALUE )
            throw std::exception("Failed to allocate shared memory.");

    if( GetLastError() == ERROR_ALREADY_EXISTS )
            shared_ = true;

    address_ = MapViewOfFile(shm_, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
    if( address_ == NULL )
            throw std::exception("Failed to map shared memory.");

    if( !shared_ )
            std::memset(address_, 0, size);

    mtx_ = CreateMutex(NULL, FALSE, (name + "MTX").c_str());
    if( mtx_ == INVALID_HANDLE_VALUE )
            throw std::exception("Failed to create shared mutex.");
    }

    CSharedMem::~CSharedMem()
    {
    UnmapViewOfFile(address_);
    CloseHandle(mtx_);
    }
    void* CSharedMem::GetAddress() const
    {
    if(WaitForSingleObject(mtx_, INFINITE) != WAIT_OBJECT_0)
            throw std::exception("Failed to obtain access to shared memory.");

    return address_;
    }

    void CSharedMem::ReleaseAddress()
    {
            ReleaseMutex(mtx_);
    }

    bool CSharedMem::IsShared() const
    {
            return shared_;
    }
4

2 に答える 2

4

上記のコメントに続いて、これは思ったほど単純ではありません。プロセス間で共有メモリを使用している場合、STL コンテナーを渡すことはできません。

ただし、boost::interprocessライブラリ内のコンテナーを使用することはできます。このライブラリは、共有メモリ セグメント内で使用できるコンテナー (ベクター、デキュー、セット、マップ) を具体的に提供し、ドキュメントには多くの例が記載されています。

于 2012-06-20T03:05:52.710 に答える
4

このロジックには何か怪しいものがあります:

void * ptr = shMem->GetAddress();
std::map<int,int> myMap;
ptr = &myMap;
shMem->ReleaseAddress();

でアドレスを取得しますが、ローカル変数をshMem->GetAddress()宣言してから、ローカル変数のアドレスをmyMap割り当てptrます。ptrこれは、その共有メモリを実際に指す必要がなくなることを意味します。

あなたがここで何をしようとしているのかわからないので、これに対する修正が何であるかわかりません。共有メモリをキャストするつもりなら、マップへのポインターになる必要があります。おそらく、次のことを意味していました。

void * ptr = shMem->GetAddress();

/* Construct a map at the given address using placement new. */
new (ptr) std::map<int, int>();
shMem-ReleaseAddress();

後で、マップを取得できます。

void* ptr = shMem->GetAdress();

/* Note the use of a reference here so we don't just make a copy. */
std::map<int,int> myMap& = *static_cast<std::map<int,int> *> (ptr);

とは言っても、内部で割り当てられたポインターmapは共有ではなく、それらを作成するプロセスに対してローカルになるため、これが機能するかどうかは非常に疑わしいです。これを正しく機能させるには、おそらくアロケーターで何か凝ったことをする必要があるでしょう。

お役に立てれば!

于 2012-06-20T02:22:33.960 に答える