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のオブジェクトが破棄されます。これは単に機能しません。
どのMSVCバージョンですか? –
何の価値があるのか、Clangは空のリストには何も割り当てず、リストをプッシュして破棄するときに割り当てられたのと同じアドレスを割り当て解除します。 –
@ T.C。これはVC2013とVC2017の両方で実際に発生します。 –