bicu
bicu

Reputation: 119

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

Upvotes: 11

Views: 1276

Answers (1)

Zang MingJie
Zang MingJie

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

Related Questions