The leak is in your own code: Your custom_delete
fails to call the destructor for the std::list
object--it directly calls operator delete
to deallocate the memory without invoking the destructor.
If you fix your program to correctly destroy the list, you will observe no leak (the program prints 0):
auto x = custom_new custom_list<int>;
x->~list(); // Destroy the list
custom_delete(x);
std::cout << the_manager.allocations << std::endl;
So, why do you only see the leak with the Visual C++ std::list
implementation? The Visual C++ implementation always allocates a sentinel node for empty list objects, to ensure that when a list is moved (or when two lists are swapped), end iterators are not invalidated. The Standard Library implementation(s) that you are using with gcc and clang apparently do not do this.