Reputation: 119
In the following test program, the memory allocated by the std::map
is not deallocated. All in all we allocate roughly 2.2 GB of memory, which is never released, although we do a swap with an empty container.
When changing the std::map< std::map >
to become a std::map< std::vector >
, the memory is actually released.
I have checked the code with valgrind, which obiously does not find any leaks.
Why is this the case, and how can I change the behavior?
#include <cstdlib>
#include <iostream>
#include <vector>
#include <map>
#include <chrono>
#include <thread>
class Test
{
public:
std::vector< std::pair< int, int > > myContainer;
std::map<int,int> myMap;
Test(){
for( int i = 0 ; i < 10000; i++ ){
std::pair<int, int> pair = std::make_pair<int, int>( rand(), int( i ) );
//myContainer.push_back( pair );
myMap.insert( pair );
}
}
};
int main()
{
std::map<int,Test> myContainer1;
for( int i = 0 ; i < 5000; i++ ){
myContainer1.insert( std::make_pair<int, Test>( rand(), Test() ) );
}
std::cout << "ready!" << std::endl;
std::this_thread::sleep_for( std::chrono::milliseconds( 5000 ) );
std::cout << "cleaning..." << std::endl;
{
std::map<int,Test> tmp;
myContainer1.swap( tmp );
}
std::cout << "cleaning ready!" << std::endl;
std::this_thread::sleep_for( std::chrono::milliseconds( 15000 ) );
return 0;
}
Upvotes: 11
Views: 1276
Reputation: 5275
the internal of std::map
uses black/red tree to store objects, which contains many small object, but std::vector
stores objects continuously, using a large flat memory block.
glibc
maintains different type of memory differently.
When requesting small objects, usually memory pool is used to avoid external fragments, but will causing internal fragments when the object freed, and the internal fragments will never return to the system.
When requesting large blocks, glibc alloc a large memory block, which may contains external fragments. but when freed, the memory will return to the system.
Upvotes: 10