MSVC中的C++自定义STL分配器错误?

问题描述:

我觉得在MSVC++中发现了一个错误。或者,也许这是缺乏我的知识,我错过了代码中的东西。我创建了一个自定义分配器:MSVC中的C++自定义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() 

如果你仔细看分配功能调用另一个对象并释放()另一个!而且为什么他们在空的forward_list上执行分配?这也适用于其他容器。在GCC上工作得很好。我会感谢所有的想法!

编辑

我想指出的是,有完全没问题,当我使用malloc和free。但是,如果我的Allocator使用自己的内存管理机制,那么在创建用于释放的对象557863137460之前,您会发现地址为557863137412的对象用于分配。这将无法正常工作。

+1

哪个MSVC版本? –

+0

对于它的价值,Clang不会为空列表分配任何内容,并且释放与推入和销毁列表时分配的地址相同的地址。 –

+0

@ T.C。这实际上发生在两个:VC2013和VC2017上。 –

没有错误。

如果你仔细看看allocate功能被称为不同的对象和deallocate()在另一个!

您正在打印分配器的地址,而不是分配的内存(de)。分配器的副本应该能够释放彼此分配的内存,并且允许实现*地复制分配器。 (特别是,在这种情况下,它看起来就像是重新绑定前的分配和释放存储的分配。)

而且为什么他们对空forward_list进行分配?

只有当您在调试模式下构建时,您才会看到此内容,其中(除其他外)激活其迭代器调试机器。该机器需要额外的内存,这是在构建容器时分配的,并在销毁容器时释放。

+0

地址为557863137412的对象用于分配,在创建557863137460之前将其销毁,然后用于释放。对我来说,它看起来是越野车。或者,也许我应该使用某种移动构造函数或类似的东西?在我使用malloc和free之前,完全没有问题。但是,如果我的Allocator管理内存,并且每个实例都有自己的缓冲区来执行此操作,则无法工作。不过好的一点是它只发生在调试中。 –

+0

@noonespecial“,每个实例都有自己的缓冲区来做到这一点”这不是分配器的工作原理。分配器*必须*可以*复制,复制*必须*等同(包括能够释放彼此分配的内存)。 –

+0

好吧,我现在看到。谢谢你的解释。我认为在每个单独的分配器实例上工作会非常有用。 –