Custom allocator to track std::vector

Source code

#include <memory>
#include <iostream>
#include <vector>

template<typename T>
struct TrackingAllocator : public std::allocator<T>
{
  template<typename U> struct rebind
  {
    typedef TrackingAllocator other;
  };

  T* allocate(size_t n, const void* hint = 0)
  {
    T* p = std::allocator<T>::allocate(n, hint);
    std::cout << "Allocated " << n * sizeof(T)
              << " bytes at " << p << std::endl;
    return p;
  }

  void deallocate(T* p, size_t n) 
  {
    std::allocator<T>::deallocate(p, n);
    std::cout << "Deallocated " << n * sizeof(T)
              << " bytes at " << p << std::endl;
  }
};

int main()
{
  std::vector<int, TrackingAllocator<int>> vec = {1, 2, 3};
  vec.push_back(4);
  vec.push_back(5);
  vec.push_back(6);
  vec.push_back(7);
  return 0;
}
$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609

$ g++ main.cpp -std=c++11 -g

Debugging

$ gdb a.out
(gdb) b 32
(gdb) r
Allocated 12 bytes at 0x615c20

Breakpoint 1, main () at main.cpp:32
32	  vec.push_back(4);
(gdb) x/3w 0x615c20
0x615c20:	1	2	3
(gdb) n
Allocated 24 bytes at 0x616050
Deallocated 12 bytes at 0x615c20
33	  vec.push_back(5);
(gdb) x/6w 0x616050
0x616050:	1	2	3	4
0x616060:	0	0
(gdb) n
34	  vec.push_back(6);
(gdb) x/6w 0x616050
0x616050:	1	2	3	4
0x616060:	5	0
(gdb) n
35	  vec.push_back(7);
(gdb) x/6w 0x616050
0x616050:	1	2	3	4
0x616060:	5	6
(gdb) n
Allocated 48 bytes at 0x616070
Deallocated 24 bytes at 0x616050
36	  return 0;
(gdb) x/12w 0x616070
0x616070:	1	2	3	4
0x616080:	5	6	7	0
0x616090:	0	0	0	0

Result

As soon as the std::vector runs out of memory its default allocator (std::allocator<T>) allocates a new chunk of memory which provides twice as much memory as the last one and deallocates the old one.