MSVC 中的 C++ 自定义 STL 分配器错误?
C++ Custom STL allocator bug in MSVC?
我认为在 MSVC++ 中发现了一个错误。或者这可能是我缺乏知识,我在代码中遗漏了一些东西。我创建了一个自定义分配器:
#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()
如果你仔细看,allocate 函数是在不同的对象上调用的,而 deallocate() 是在另一个对象上调用的!此外,为什么他们在空 forward_list 上执行分配?这对其他容器也是如此。并且在 GCC 上运行良好。我将感谢所有想法!
编辑
我想指出的是,我使用malloc和free时完全没有问题。但是,如果我的分配器使用自己的内存管理机制,您会发现用于分配的地址为 557863137412 的对象在创建用于释放的对象 557863137460 之前被销毁。这根本行不通。
没有错误。
If you look carefully allocate
function is called on different object and deallocate()
on another!
您正在打印分配器的地址,而不是(取消)分配的内存。分配器的副本应该能够解除分配彼此分配的内存,并且允许实现自由地复制分配器。 (特别是,在这种情况下,它看起来像是在分配和解除分配之前重新绑定存储的分配器。)
Moreover why do they perform allocation on empty forward_list
?
只有在调试模式下构建时才会看到这一点,调试模式(除其他外)会激活他们的迭代器调试机制。该机器需要额外的内存,这些内存在构建容器时分配并在容器销毁时释放。
我认为在 MSVC++ 中发现了一个错误。或者这可能是我缺乏知识,我在代码中遗漏了一些东西。我创建了一个自定义分配器:
#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()
如果你仔细看,allocate 函数是在不同的对象上调用的,而 deallocate() 是在另一个对象上调用的!此外,为什么他们在空 forward_list 上执行分配?这对其他容器也是如此。并且在 GCC 上运行良好。我将感谢所有想法!
编辑
我想指出的是,我使用malloc和free时完全没有问题。但是,如果我的分配器使用自己的内存管理机制,您会发现用于分配的地址为 557863137412 的对象在创建用于释放的对象 557863137460 之前被销毁。这根本行不通。
没有错误。
If you look carefully
allocate
function is called on different object anddeallocate()
on another!
您正在打印分配器的地址,而不是(取消)分配的内存。分配器的副本应该能够解除分配彼此分配的内存,并且允许实现自由地复制分配器。 (特别是,在这种情况下,它看起来像是在分配和解除分配之前重新绑定存储的分配器。)
Moreover why do they perform allocation on empty
forward_list
?
只有在调试模式下构建时才会看到这一点,调试模式(除其他外)会激活他们的迭代器调试机制。该机器需要额外的内存,这些内存在构建容器时分配并在容器销毁时释放。