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

时间:2017-08-26 20:49:20

标签: c++ c++11 stl allocator

我认为在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()

如果你仔细看看分配函数是在不同的对象上调用而deallocate()在另一个对象上调用的!那么为什么他们在空的forward_list上执行分配呢?对于其他容器,这也是这样的。在GCC上工作得很好。我会感谢所有的想法!

修改

我想指出当我使用malloc和free时完全没有问题。但是,如果我的Allocator使用自己的内存管理机制,您会发现用于分配的地址557863137412处的对象在创建用于取消分配的对象557863137460之前被销毁。这根本行不通。

1 个答案:

答案 0 :(得分:4)

没有错误。

  

如果你仔细观察allocate函数在不同的对象上调用,deallocate()在另一个对象上调用!

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

  

此外,为什么他们在空forward_list上执行分配?

只有在构建调试模式时才会看到这种情况,调试模式会激活其迭代器调试机制。该机器需要额外的内存,这些内存在容器的构造上分配,并在破坏容器时解除分配。