2013-07-26 4 views
6

ho riscontrato il seguente problema e non sono sicuro se ho torto o si tratta di un bug davvero strano. Riempio una vasta gamma di stringhe e voglio che venga cancellato a un certo punto. Ecco un esempio minimovector <string> non cancella memoria dopo lo scope

#include <string> 
#include <vector> 
#include <unistd.h> //sleep 
#include <iostream> 

int main(){ 
    { 
     std::vector<std::string> strvec; 
     for(long i = 0; i < 1000000; ++i){ 
      std::string out = "This is gonna be a long string just to fill up the memory used by this fucking pthread\n"; 
      strvec.push_back(out); 
     } 
     std::cout << "finished loading 1st\n"; 
     sleep(10); // to monitor any changes  
    } 
    std::cout << "out of scope\n"; 
    sleep(10); 
    return 0; 
} 

il mio problema è, se a monitorare l'utilizzo della memoria con 'top', diminuisce utilizzo della memoria solo con una piccola quantità (credo che la sua, probabilmente il sovraccarico vettore), ma la maggior parte non sembra liberato. Come mai? Ho provato lo stesso scenario con "long long", ma qui è andato tutto bene.

Il riferimento std :: vector indica che, se i valori contenuti non sono puntatori, i distruttori vengono richiamati. Sembra non vero per stringa però ...

Apprezzo ogni risposta.

(per comodità: sto usando debian 64Bit linux con g ++ 4.7.2)

EDIT: Grazie per le risposte finora.

a questo punto ho un utilizzo profilato dell'heap con il vagrind massiccio e (sì, in realtà come previsto) viene correttamente liberato al punto che dovrebbe. Ma perché in effetti vedo un cambiamento nell'uso con un numero intero enorme, ma non con le stringhe (anche nella parte superiore)?

Ho bisogno di essere un po 'considerevole, perché ho bisogno di essere in grado di liberare la mia memoria in determinati momenti per un'applicazione server multithread, che probabilmente verrà eseguita diverse settimane o più senza essere riavviata. Quando so davvero quando il gestore di memoria C++ decide di restituire alcuni mem al sistema operativo?

+0

Prova il debugging con [valgrind] (http://valgrind.org/) che ti dirà se la memoria è gratuita o meno, e probabilmente sarebbe più utile di "top". – Couchy311

+0

Cosa c'entra con l'insistenza della gente che la memoria venga sprecata? La memoria libera non fa * niente * - non è migliore della memoria che non è nel computer. Solo la memoria che è * in uso * è utile. –

risposta

6

Questo è uno specifico dell'utilizzo del comando top, non dello std::vector. Il problema è che la memoria liberata dalle strutture dati non viene rilasciata al sistema operativo, il livello con cui il comando top monitora l'utilizzo della memoria. La memoria che il sistema operativo ha dato al tuo programma rimane con il tuo programma fino a quando il gestore della memoria di C++ decide che è ora di liberare memoria nel sistema operativo.

Il motivo è che l'allocazione della memoria dal sistema operativo è relativamente costosa e deve essere eseguita in blocchi relativamente grandi. Il gestore della memoria della libreria di runtime C++ ottiene la memoria dal sistema operativo "all'ingrosso", quindi la distribuisce alle parti del programma secondo necessità.

Se si desidera verificare che la memoria venga effettivamente recuperata, utilizzare uno strumento che monitora l'utilizzo della memoria a un livello inferiore, ad esempio valgrind.

4

Anche se si libera la memoria correttamente, la libreria standard non rende necessaria la memoria di nuovo sul sistema operativo.

Ad esempio, quando si assegna per la prima volta tutta la memoria, la libreria assegna un po 'di spazio di indirizzi di memoria virtuale dal sistema operativo (probabilmente con mmap(2)) e lo distribuisce. Ma quando hai finito con quella memoria, si blocca sullo spazio degli indirizzi virtuali supponendo che potresti voler recuperare quella memoria in un secondo momento, quindi non chiama munmap(2) per rimuovere lo spazio degli indirizzi virtuali.

Quindi, anche se tutta la memoria è stata correttamente liberata dal punto di vista del tuo programma, tutto il sistema operativo vede che hai assegnato un po 'di memoria virtuale, ma che poi non l'hai mai liberato. Ecco perché top(1) segnala che l'utilizzo della memoria non diminuisce, ma non c'è nulla di cui preoccuparsi. Quando il tuo programma ha ancora bisogno di memoria, lo allocerà dallo spazio degli indirizzi virtuali che hai già, quindi non vedrai aumentare l'uso della memoria apparente fino a quando tutta la memoria non sarà esaurita.

0

Come indicato in altre risposte, la memoria è ancora disponibile per il processo e non viene liberata al di fuori di esso fino alla chiusura del programma. Se vuoi un allocatore che lo faccia, puoi provare a usare jemalloc che può ridistribuirlo al sistema operativo ed è molto utile in applicazioni scalabili multi-thread come facebook ma come con qualsiasi altra cosa ci sono altri costi.