When I run the next code in VS2017:
#include <boost/pool/pool_alloc.hpp>
#include <map>
#include <iostream>
int main()
{
using Map = std::map<int, int, std::less<int>, boost::pool_allocator<std::pair<const int, int>>>;
using Pool = boost::singleton_pool<boost::pool_allocator_tag, sizeof(Map)>;
Map temp;
for (int i = 1; i < 5; i++) temp[i] = i;
std::cout << "First addresses:\n";
for (auto& kv : temp) std::cout << &kv.second << "\n";
temp.clear();
Pool::purge_memory();
Map temp2;
for (int i = 1; i < 5; i++) temp2[i] = i;
std::cout << "Second addresses:\n";
for (auto& kv : temp2) std::cout << &kv.second << "\n";
temp2.clear();
Pool::purge_memory();
return 0;
}
I get the output:
First addresses:
02A108F4
02A1090C
02A10924
02A1093C
Second addresses:
02A1090C
02A10924
02A1093C
02A10954
Live example
This behavior seems incorrect: what happened to address 02A108F4? It seems it was not returned to the pool during the purge.
This doesn't happen when I use a std::vector instead of a std::map.
gcc also seems to return the memory correctly: Live example.
Is this a bug in VS2017?
You're assuming things about the implementation details of the pool. You may well be right there is a loss, but you can't conclude this from the allocation patterns you see.
Also, you're purging the memory for the pool allocator associated with sizeof(int). However, the value_type is already std::pair<int const, int>, and that leaves the fact that the map implementation allocates an unspecified node-type instead.
Oh, and the reason your allocator worked is precisely the same: the container implementation knows you cannot possibly provide the right type of allocator, since the allocated type is unspecified. Therefore it will always rebind to get the required type.
So, at least make it
Live On Rextester
#include <boost/pool/pool_alloc.hpp>
#include <map>
#include <iostream>
using Map = std::map<int, int, std::less<int>, boost::pool_allocator<int>>;
using Pool = boost::singleton_pool<boost::pool_allocator_tag, sizeof(Map::value_type)>;
void foo() {
Map temp;
for (int i = 1; i < 5; i++) temp[i] = i;
std::cout << "First addresses:\n";
for (auto& kv : temp) std::cout << &kv.second << "\n";
}
int main()
{
foo();
Pool::purge_memory();
foo();
Pool::purge_memory();
}
This, though is still assuming implementation details. I think c++17 gives you some more information to work with (http://en.cppreference.com/w/cpp/container/node_handle) or otherwise you could see wheter Boost Container has the relevant details: https://www.boost.org/doc/libs/1_51_0/doc/html/boost/container/map.html#id463544-bb
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With