mercredi 6 juin 2018

Segfault in minimal example of scoped_allocator_adaptor used with vector of unordered_map

I have recently learned about custom allocators in C++11 and am trying to use them in my application. However I am running into a segfault, which can be reproduced by the following minimal example:

#include <vector>
#include <unordered_map>
#include <scoped_allocator>

template<class T> struct custom_allocator {
    typedef T value_type;
    custom_allocator() noexcept {}
    template <class U> custom_allocator (const custom_allocator<U>&) noexcept {}
    T* allocate (std::size_t n) { return static_cast<T*>(::operator new(n*sizeof(T))); }
    void deallocate (T* p, std::size_t n) { ::delete(p); }
    template <typename U> constexpr bool operator==(const custom_allocator<U>&) const { return true; }
    template <typename U> constexpr bool operator!=(const custom_allocator<U>&) const { return false; }
};

template<class T> using custom_scoped_allocator = std::scoped_allocator_adaptor<custom_allocator<T> >;

typedef std::unordered_map<int, int, std::hash<int>, std::equal_to<int>,
                           custom_scoped_allocator<std::pair<const int, int> > > MyMap;

typedef std::vector<MyMap, custom_scoped_allocator<MyMap> > MyVector;

int main() {
    MyVector vec(1);
    vec[0][0] = 0;
    return 0;
}

The custom allocator is exactly the one suggested in the example at http://www.cplusplus.com/reference/memory/allocator_traits/ It is then combined with std::scoped_allocator_adaptor as I have seen suggested in a few places on the internet.

The code compiles fine with gcc 5.4.0 using g++ -g3 -O0 -std=c++11 -march=core-avx-i -o tmpalloc tmpalloc.cpp. When I attempt to run it, a segfault is reported starting with

*** Error in `./tmpalloc': double free or corruption (fasttop): 0x0000000000ae3c90 ***

If I recompile using AddressSanitizer, I get the following details about the double free: https://pastebin.com/raw/xy2NQtD0 (Sorry for the pastebin but it is not pretty.) Basically, the destructor for an unordered_map object seems to be called twice.

What am I doing wrong?

Aucun commentaire:

Enregistrer un commentaire