简体   繁体   中英

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!

EDIT

I would like to point out that there is completely no problem when I use malloc and free. However if my Allocator uses own mechanisms for memory management, you will find that object at address 557863137412 used for allocation is destroyed before creation of object 557863137460 which is used for deallocation. This will simply not work.

There is no bug.

If you look carefully allocate function is called on different object and deallocate() on another!

You are printing the address of the allocator, not the memory (de)allocated. Copies of an allocator are supposed to be able to deallocate memory allocated by one another, and implementations are allowed to copy allocators freely. (In particular, in this case it looks like it was rebinding the stored allocator prior to the allocate and deallocate.)

Moreover why do they perform allocation on empty forward_list ?

You only see this when you build in debug mode, which (among other things) activates their iterator debugging machinery. That machinery requires additional memory that is allocated on construction of the container and deallocated on destruction of the container.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM