[Bug libstdc++/86189] New: not equal allocators not behaving as expected
rianquinn at gmail dot com
gcc-bugzilla@gcc.gnu.org
Sun Jun 17 20:07:00 GMT 2018
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.
More information about the Gcc-bugs
mailing list