Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does std::map< std::map > not deallocate memory?

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;
}
like image 493
bicu Avatar asked Jun 02 '16 09:06

bicu


1 Answers

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.

like image 163
Zang MingJie Avatar answered Oct 24 '22 04:10

Zang MingJie