[LLVMbugs] [Bug 22366] New: std::map does not call allocator_type::destroy for elements if the map moves to another map and their allocators are not equal

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Tue Jan 27 20:12:21 PST 2015


http://llvm.org/bugs/show_bug.cgi?id=22366

            Bug ID: 22366
           Summary: std::map does not call allocator_type::destroy for
                    elements if the map moves to another map and their
                    allocators are not equal
           Product: libc++
           Version: unspecified
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: All Bugs
          Assignee: unassignedclangbugs at nondot.org
          Reporter: kariya_mitsuru at hotmail.com
                CC: llvmbugs at cs.uiuc.edu, mclow.lists at gmail.com
    Classification: Unclassified

Created attachment 13747
  --> http://llvm.org/bugs/attachment.cgi?id=13747&action=edit
g++ -v

Please see the sample code below. (Sorry, too long)

===================================== sample code
=====================================
#include <map>
#include <utility>
#include <iostream>

template <typename T>
struct MyAlloc {
    typedef T value_type;
    MyAlloc(int i = 0) : i(i) {}
    template <typename U>
    MyAlloc(const MyAlloc<U>& o) : i(o.i) {}
    T* allocate(std::size_t n) {
        void* p = ::operator new(sizeof(T) * n);
        std::cout << "allocate:" << p << std::endl;
        return static_cast<T*>(p);
    }
    void deallocate(T* c, std::size_t) {
        void* p = c;
        std::cout << "deallocate:" << p << std::endl;
        ::operator delete(p);
    }
    template <typename U, typename... Args>
    void construct(U* c, Args...args) {
        void* p = c;
        std::cout << "construct:" << p << std::endl;
        ::new(p) U(std::forward<Args>(args)...);
    }
    template <typename U>
    void destroy(U* p) {
        std::cout << "destruct:" << static_cast<const void*>(p) << std::endl;
        p->~U();
    }
    int i;
};

template <typename T>
inline bool operator==(const MyAlloc<T>& lhs, const MyAlloc<T>& rhs)
{
    return lhs.i == rhs.i;
}

template <typename T>
inline bool operator!=(const MyAlloc<T>& lhs, const MyAlloc<T>& rhs)
{
    return lhs.i != rhs.i;
}

struct T {
    T(int i) : i(i) {
        std::cout << "T(int):"
                  << static_cast<const void*>(this) << '(' << i << ')' <<
std::endl;
    }
    T(const T& o) : i(o.i + 10) {
        std::cout << "T(const T&):"
                  << static_cast<const void*>(&o) << '(' << o.i << ") -> "
                  << static_cast<const void*>(this) << '(' << i << ')' <<
std::endl;
    }
    T& operator=(const T& o) {
        i = o.i + 30;
        std::cout << "operator=(const T&):"
                  << static_cast<const void*>(&o) << '(' << o.i << ") -> "
                  << static_cast<const void*>(this) << '(' << i << ')' <<
std::endl;
        return *this;
    }
    ~T() {
        std::cout << "~T():"
                  << static_cast<const void*>(this) << '(' << i << ')' <<
std::endl;
    }
    int i;
};

int main()
{
    using map = std::map<int, T, std::less<int>, MyAlloc<std::pair<const int,
T>>>;

    std::cout << "1" << std::endl;
    map m1;
    m1.emplace(1, 2);
    std::cout << "2" << std::endl;
    map m2(std::move(m1), MyAlloc<map::value_type>(1));
    std::cout << "3" << std::endl;
}
===================================== sample code
=====================================

======================================= output
=======================================
1
allocate:0xd1f010
construct:0xd1f02c
T(int):0xd1f030(2)
2
allocate:0xd1f040
T(const T&):0xd1f030(2) -> 0x7fff2c3c7714(12)
construct:0xd1f05c
T(const T&):0x7fff2c3c7714(12) -> 0xd1f060(22)
~T():0x7fff2c3c7714(12)
deallocate:0xd1f010
3
destruct:0xd1f05c
~T():0xd1f060(22)
deallocate:0xd1f040
======================================= output
=======================================

cf. http://melpon.org/wandbox/permlink/JDPKzTVRwMq9zYZl


The output shows that destroy for 0xd1f02c (and ~T() for 0xd1f030(2)) is not
called but deallocate for 0xd1f010 is called.

I think that the destroy (and destructor) should be called.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20150128/5c20e844/attachment.html>


More information about the llvm-bugs mailing list