2016-06-02 13 views
10

Nel seguente programma di test, la memoria allocata da std::map non è deallocata. Tutto sommato, allociamo circa 2,2 GB di memoria, che non viene mai rilasciata, anche se facciamo uno scambio con un contenitore vuoto.Perché std :: map < std::map > non rilascia la memoria?

Quando si modifica std::map<std::map> in uno std::map<std::vector>, la memoria viene effettivamente rilasciata.

Ho controllato il codice con valgrind, che non rileva alcuna perdita.

Perché è questo il caso e come posso modificare il comportamento?

#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

Come si determina che la memoria non viene rilasciata? –

+1

Ho usato un monitor di sistema, la dimensione della memoria residente. Quando si utilizza la 'mappa < vector >' vedo che il processo RSS scende a pochi MB. Quando si utilizza 'map ', l'RSS rimane a 2 GB. – bicu

+0

@bicu che non significa necessariamente che la memoria non viene rilasciata (sebbene RSS * sia * * di solito * un indicatore migliore di VSIZE). 'valgrind' di solito riporta (tra le altre cose) la quantità di memoria ancora allocata alla fine di un programma ed è molto più affidabile rispetto a quella delle statistiche di monitoraggio delle risorse. Quali valori stai vedendo lì? – Andrew

risposta

10

l'interno std::map utilizza nero albero/rosso per memorizzare gli oggetti, che contiene molte piccole oggetto, ma std::vector negozi oggetti continuo, utilizzando un grande blocco di memoria piatta.

glibc conserva diversi tipi di memoria in modo diverso.

Quando si richiedono oggetti piccoli, in genere viene utilizzato il pool di memoria per evitare i frammenti esterni, ma causando frammenti interni quando l'oggetto viene liberato e i frammenti interni non ritorneranno mai nel sistema.

Quando si richiedono blocchi di grandi dimensioni, glibc alloca un grande blocco di memoria, che può contenere frammenti esterni. ma una volta liberato, la memoria tornerà nel sistema.

Problemi correlati