https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86189
Bug ID: 86189 Summary: not equal allocators not behaving as expected Product: gcc Version: 8.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: rianquinn at gmail dot com Target Milestone: --- I think this is a bug, but I am dealing with allocators so I am not 100% sure here. I have created a really simple allocator for testing. The allocators are NOT equal, and I have instructed the containers to propagate the allocator using the propagate_on_container_copy_assignment alias set to true. Propagation occurs, but during the destruction of the containers, the old allocator is somehow being used. Whats worse is the newly allocated memory that was created using one allocator, is deallocated using another, even though they are not equal. Seems like a bug. Here is the allocator I have created: template<typename T> class myallocator4 { public: using value_type = T; using pointer = T *; using size_type = std::size_t; using propagate_on_container_copy_assignment = std::true_type; using is_always_equal = std::false_type; public: myallocator4() = default; template <typename U> myallocator4(const myallocator4<U> &other) noexcept { (void) other; } pointer allocate(size_type n) { if (auto ptr = static_cast<pointer>(malloc(sizeof(T) * n))) { std::cout << "A: " << this << " ptr: " << ptr << '\n'; return ptr; } throw std::bad_alloc(); } void deallocate(pointer p, size_type n) { (void) n; std::cout << "D: " << this << " ptr: " << p << '\n'; free(p); } }; template <typename T1, typename T2> bool operator==(const myallocator4<T1> &, const myallocator4<T2> &) { return false; } template <typename T1, typename T2> bool operator!=(const myallocator4<T1> &, const myallocator4<T2> &) { return true; } Here is the test case: TEST_CASE("copy container, propogate") { std::cout << "copy container, propogate\n"; std::list<int, myallocator4<int>> mylist1; std::list<int, myallocator4<int>> mylist2; mylist1.push_back(1); mylist1.push_back(2); mylist1.push_back(3); mylist2.push_back(4); mylist2.push_back(5); mylist2.push_back(6); std::cout << "--------------------------" << '\n'; mylist2 = mylist1; std::cout << "--------------------------" << '\n'; } And here is the result: copy container, propogate A: 0x7ffce414af40 ptr: 0x562e4822ca30 A: 0x7ffce414af40 ptr: 0x562e4822cbf0 A: 0x7ffce414af40 ptr: 0x562e4822cc40 A: 0x7ffce414af60 ptr: 0x562e48237880 A: 0x7ffce414af60 ptr: 0x562e48233fe0 A: 0x7ffce414af60 ptr: 0x562e4822cc60 -------------------------- D: 0x7ffce414af60 ptr: 0x562e48237880 D: 0x7ffce414af60 ptr: 0x562e48233fe0 D: 0x7ffce414af60 ptr: 0x562e4822cc60 A: 0x7ffce414ae40 ptr: 0x562e4822cc60 A: 0x7ffce414ae40 ptr: 0x562e48233fe0 A: 0x7ffce414ae40 ptr: 0x562e48237880 -------------------------- D: 0x7ffce414af60 ptr: 0x562e4822cc60 D: 0x7ffce414af60 ptr: 0x562e48233fe0 D: 0x7ffce414af60 ptr: 0x562e48237880 D: 0x7ffce414af40 ptr: 0x562e4822ca30 D: 0x7ffce414af40 ptr: 0x562e4822cbf0 D: 0x7ffce414af40 ptr: 0x562e4822cc40 As can be seen, the allocator at 0x7ffce414af60 (which is the original allocator for the second list) is used to deallocate memory from 0x7ffce414ae40, even though the allocators are not equal.