7

共有メモリに unordered_map を作成しようとしています。アロケーターを使用して目的をサーバーにしています。

コード

void *addr;
void *pool;
int shmid;

template<class T>
class MyPoolAlloc {
private:
public:
    typedef size_t     size_type;
    typedef ptrdiff_t  difference_type;
    typedef T*         pointer;
    typedef const T*   const_pointer;
    typedef T&         reference;
    typedef const T&   const_reference;
    typedef T          value_type;

   template<class X>
   struct rebind
   { typedef MyPoolAlloc<X> other; };

   MyPoolAlloc() throw() {
   }
   MyPoolAlloc(const MyPoolAlloc&) throw()  {
   }

   template<class X>
   MyPoolAlloc(const MyPoolAlloc<X>&) throw() {
   }

   ~MyPoolAlloc() throw() {
   }

  pointer address(reference __x) const { return &__x; }

  const_pointer address(const_reference __x) const { return &__x; }

  pointer allocate(size_type __n, const void * hint = 0) {
      pointer tmp = static_cast<T*>(addr);
      addr = (void*)((char*)addr + __n);
      return tmp;
  }

  void deallocate(pointer __p, size_type __n) {
      // pMyPool->Free(reinterpret_cast<void *>(__p));
  }

 size_type max_size() const throw() {
    //return size_t(-1) / sizeof(T);
  }

 void construct(pointer __p, const T& __val) {
     ::new(__p) T(__val);
  }

 void destroy(pointer __p) {
    //__p->~T();
  }
};

typedef std::unordered_map<int, int, std::hash<int>, std::equal_to<int>,  MyPoolAlloc<std::pair<const int,int>> > Map;

int main ()
{
    shmid = shmget(shm_key, 1000, IPC_CREAT | IPC_EXCL | 644);
    if(shmid == -1){
            std::cerr << "Failed to create the shared segment." << strerror(errno)<< std::endl;
            exit(-1);
    }

    addr = shmat(shmid, NULL, 0);
    pool = addr;
    if(addr == (void*)-1){
            std::cerr << "Failed to attach the segment to the process." << std::endl;
            shmctl(shmid, IPC_RMID, 0);
            exit(-1);
    }

    Map *m = new(pool) Map;

    m->insert(std::pair<int, int>(2,4));

    shmdt(addr);
    shmctl(shmid, IPC_RMID, 0);

    return 0;
}

共有メモリ アドレスのマップにメモリを割り当てています。そして、要素にはアロケータークラスの allocate() 関数が使用されると思います。しかし、割り当て関数を使用してマップの要素にメモリを割り当てる方法を理解できません。マップに挿入しようとしている行で算術例外が発生しています。

誰かがメモリレイアウトがどうあるべきかを理解するのを手伝ってくれませんか?

ありがとう。

4

1 に答える 1

7

前回 this について質問したときに言ったように、ポインタを共有メモリに保存して、それらが複数のプロセスで使用できると期待することはできません。boost::unordered_map以前と同様に、と組み合わせてboost::interprocess::allocator使用​​することをお勧めします。

本当に独自のアロケータを書きたい場合は、オフセットを共有メモリ ブロックに格納し、そこから正しいアドレスを再構築できるカスタム ポインタが必要になります。これを自分でやろうとすることはお勧めしません。非常に手間がかかるだけでなく、一部の実装がstd::unordered_map型にはまらないポインター型で正しく機能しないことに気付くかもしれません。実際、標準に準拠した共有メモリ用のアロケータを作成するのは不可能かもしれないと私は考えています。それ以外の場合、Boost アロケーターは、特別な Boost バージョンだけでなく、すべての標準コンテナーで確実に使用できます。

ところで、__p(2 つのアンダースコアを含む) のような予約名を独自のコードで使用しないでください。これらは、標準ライブラリの実装でのみ使用する必要があります。

于 2012-08-07T08:59:17.327 に答える