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;
}
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.
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