简体   繁体   English

为什么std :: map <std :: map>没有释放内存?

[英]Why does std::map< std::map > not deallocate memory?

In the following test program, the memory allocated by the std::map is not deallocated. 在以下测试程序中, std::map分配的内存不会被释放。 All in all we allocate roughly 2.2 GB of memory, which is never released, although we do a swap with an empty container. 总而言之,我们分配大约2.2 GB的内存,虽然我们使用空容器进行交换,但它从未发布过。

When changing the std::map< std::map > to become a std::map< std::vector > , the memory is actually released. 当将std::map< std::map >更改为std::map< std::vector > ,实际释放内存。

I have checked the code with valgrind, which obiously does not find any leaks. 我已经用valgrind检查了代码,这个代码没有发现任何泄漏。

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. std::map的内部使用黑/红树来存储对象,其中包含许多小对象,但std::vector使用大型平面内存块连续存储对象。

glibc maintains different type of memory differently. glibc不同的方式维护不同类型的内存。

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. 当请求大块时,glibc分配一个大的内存块,它可能包含外部片段。 but when freed, the memory will return to the system. 但释放后,内存将返回系统。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM