为什么std :: map< std :: map>不解除记忆?

时间:2016-06-02 09:00:59

标签: c++ c++11 memory-management

在以下测试程序中,std::map分配的内存未被释放。总而言之,我们分配大约2.2 GB的内存,虽然我们使用空容器进行交换,但它从未发布过。

std::map< std::map >更改为std::map< std::vector >时,内存实际上已被释放。

我已经用valgrind检查了代码,但是很难找到任何泄漏。

为什么会这样,我该如何改变行为?

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

1 个答案:

答案 0 :(得分:10)

std::map的内部使用黑/红树来存储对象,其中包含许多小对象,但std::vector使用大型平面内存块连续存储对象。

glibc以不同的方式维护不同类型的内存。

在请求小对象时,通常使用内存池来避免外部碎片,但在释放对象时会导致内部碎片,内部碎片永远不会返回系统。

当请求大块时,glibc分配一个大的内存块,它可能包含外部片段。但释放后,内存将返回系统。