2017-08-26 4 views
1

MSVC++でバグが見つかりました。それとも、これは私の知識が不足しているため、コード内で何かが間違っていました。C++ MSVCのカスタムSTLアロケータのバグ?

#include <forward_list> 
#include <iostream> 

template <class T> 
class Allocator 
{ 
    public: 

     typedef std::size_t size_type; 
     typedef std::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 U> 
     struct rebind 
     { 
      typedef Allocator<U> other; 
     }; 

     Allocator() 
     { 
      std::cout << (ptrdiff_t) this << " Allocator()" << std::endl; 
     } 

     Allocator(const Allocator &allocator) 
     { 
      std::cout << (ptrdiff_t) this << " Allocator(const Allocator &allocator)" << std::endl; 
     } 

     template <class U> 
     Allocator(const Allocator<U> &other) 
     { 
      std::cout << (ptrdiff_t) this << " Allocator(const Allocator<U> &other)" << std::endl; 
     } 

     ~Allocator() 
     { 
      std::cout << (ptrdiff_t) this << " ~Allocator()" << std::endl; 
     } 

     pointer allocate(size_type n, std::allocator<void>::const_pointer hint = 0) 
     { 
      std::cout << (ptrdiff_t) this << " allocate()" << std::endl; 
      return (pointer) std::malloc(n * sizeof(T)); 
     } 

     void deallocate(pointer p, size_type n) 
     { 
      std::cout << (ptrdiff_t) this << " deallocate()" << std::endl; 
      std::free(p); 
     } 

     void construct(pointer p, const_reference val) 
     { 
      new (p) T(val); 
     } 

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

私は例えば、このようにそれを使用しようとすると:私は、カスタムアロケータを作成

Allocator<int> allocator; 
std::forward_list<int, Allocator<int>> memoryPoolList(allocator); 

を、私はあなたが慎重に機能を割り当てる見ればある出力

557863138612 Allocator() 
557863138648 Allocator(const Allocator<U> &other) 
557863137412 Allocator(const Allocator<U> &other) 
557863137412 allocate() 
557863137412 ~Allocator() 
557863137460 Allocator(const Allocator<U> &other) 
557863137460 deallocate() 
557863137460 ~Allocator() 
557863138648 ~Allocator() 
557863138612 ~Allocator() 

を以下ました別のオブジェクトで呼び出され、別のオブジェクトでdeallocate()が呼び出されます。さらに、空のforward_listに割り振りを行う理由は何ですか?これは他のコンテナに対してもこのように動作します。 GCCでもうまくいきます。私はすべてのアイデアに感謝します!

EDIT

私はmallocとfreeを使用する場合には問題が完全に存在しないことを指摘したいと思います。しかし、私のアロケータがメモリ管理のために独自のメカニズムを使用している場合、アロケーションに使用されるオブジェクト557863137460の作成前に、割り当てに使用されたアドレス557863137412のオブジェクトが破棄されます。これは単に機能しません。

+1

どのMSVCバージョンですか? –

+0

何の価値があるのか​​、Clangは空のリストには何も割り当てず、リストをプッシュして破棄するときに割り当てられたのと同じアドレスを割り当て解除します。 –

+0

@ T.C。これはVC2013とVC2017の両方で実際に発生します。 –

答えて

4

バグはありません。

あなたは慎重に見てallocate機能が別のオブジェクトと別のdeallocate()で呼び出された場合!

割り当てられたメモリ(de)ではなく、アロケータのアドレスが表示されます。アロケータのコピーは、互いに割り当てられたメモリを解放することができ、実装は自由にアロケータをコピーすることができます。 (それが割り当てと割り当て解除の前に保存されたアロケータを再バインドしたように、特に、この場合には見える。)

はまた、なぜそれらが空forward_listに割り当てを行いますか?

これは、デバッグモードでビルドしたときにのみ表示されます。デバッグモードでは、イテレータのデバッグ用のマシンがアクティブ化されます。その機械は、コンテナの構築時に割り当てられ、コンテナの破壊時に割り当て解除される追加のメモリを必要とする。

+0

アドレス557863137412のオブジェクトが割り当てに使用され、557863137460が作成されてから割り当て解除に使用される前に破棄されます。私にとっては外見はバギーです。または、私は何らかの種類の移動コンストラクタを使用するか、このようなものを使用する必要がありますか?私がmallocを使用しフリーになるまでは全く問題はありません。しかし、私のアロケータがメモリを管理し、各インスタンスがこれを行うための独自のバッファを持っていれば、動作しません。しかし、デバッグだけで良い点があります。 –

+0

@noonespecial "と各インスタンスはこれを行うための独自のバッファを持っています。アロケータ*は自由にコピー可能でなければならず、コピーは同等でなければなりません(お互いに割り当てられたメモリを解放することを含む)。 –

+0

さて、わかりました。ご説明をいただき、ありがとうございます。私は個々のアロケータインスタンスを処理することは非常に便利だと思います。 –

関連する問題