2016-06-02 6 views
10

次のテストプログラムでは、std::mapによって割り当てられたメモリは割り当て解除されません。私たちは空のコンテナでスワップしますが、まったくのことではなく、約2.2 GBのメモリを割り当てます。なぜstd :: map < std::map >はメモリの割り当てを解除しませんか?

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

どのようにメモリが解放されていないと判断していますか? –

+1

システムモニタ、常駐メモリサイズを使用しました。 'map < vector >'を使用すると、プロセスRSSが数MBにまで減少することがわかります。 'map 'を使用すると、RSSは2 GBのままです。 – bicu

+0

@bicuは必ずしもメモリが解放されているわけではありません(RSS *は通常は* VSIZEよりも優れたインジケータです)。 'valgrind'は、通常、プログラム終了時にまだ割り当てられているメモリの量を報告します(他のものの中でも)、リソースモニタの統計値を見るよりもはるかに信頼性があります。どのような価値観がありますか? – Andrew

答えて

10

std::mapの内部には、多数の小さなオブジェクトを含むオブジェクトを格納するために赤/黒のツリーを使用するが、std::vector格納大型フラットなメモリ・ブロックを使用して、連続的にオブジェクト。

glibcは、異なるタイプのメモリを別々に維持します。

小さなオブジェクトを要求すると、通常メモリプールは外部フラグメントを避けるために使用されますが、オブジェクトが解放されたときに内部フラグメントが発生し、内部フラグメントがシステムに返されることはありません。

大きなブロックを要求すると、glibcは大きなフラグメントを含む大きなメモリブロックを割り当てます。解放されると、メモリはシステムに戻ります。

関連する問題