samedi 26 août 2017

C++ Custom STL allocator bug in MSVC?

I think found a bug in MSVC++. Or maybe this is a lack of my knowledge and I missed something in the code. I created a custom allocator:

#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();
        }
};

When I tried to use it for example this way:

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

I got following a output

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()

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? This behaves this way for other containers too. And works pretty well on GCC. I'll be thankful for all ideas!

Aucun commentaire:

Enregistrer un commentaire