2013-07-26 6 views
6

Ich habe das folgende Problem festgestellt, und ich bin nicht wirklich sicher, ob ich falsch liege oder es ist ein wirklich seltsamer Bug. Ich fülle ein riesiges Array von Strings und möchte, dass es an einem bestimmten Punkt gelöscht wird. Hier ist ein minimales BeispielVektor <string> Speicher nicht gelöscht nach außerhalb des Bereichs

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

Mein Problem ist, wenn ich die Speichernutzung mit ‚top‘ überwachen, die Speichernutzung verringert sich nur um einen sehr kleinen Betrag (ich glaube, es ist wahrscheinlich der Vektor-Overhead), aber die meisten scheint nicht befreit. Wie kommt es? Ich testete das gleiche Szenario mit "Long Long", aber hier lief alles richtig.

Die std :: vector-Referenz besagt, dass, wenn die enthaltenen Werte keine Zeiger sind, die Destruktoren aufgerufen werden. Scheint nicht wahr für Schnur obwohl ...

Ich schätze jede Antwort.

(der Einfachheit halber: ich bin mit Debian Linux 64Bit mit g ++ 4.7.2)

EDIT: Danke für die bisherigen Antworten.

Ich habe jetzt profile Haufen Verwendung mit Vagrind-Massiv, und (ja, eigentlich wie erwartet) es wird richtig befreit an dem Punkt, den es sollte. Aber warum sehe ich tatsächlich eine Änderung in der Verwendung mit einer riesigen Ganzzahl, aber nicht mit den Strings (auch oben)?

Ich muss ein wenig beträchtlich darüber sein, weil ich in der Lage sein, meinen Speicher zu bestimmten Zeiten für eine Multithread-Server-Anwendung freizugeben, die wahrscheinlich mehrere Wochen oder mehr ohne Neustart ausgeführt wird. Wann weiß ich eigentlich, wann der C++ - Speichermanager beschließt, dem Betriebssystem etwas mitzuteilen?

+0

Versuchen Sie das Debuggen mit [Valgrind] (http://valgrind.org/) es wird Ihnen sagen, ob Speicher frei ist oder nicht, und wäre wahrscheinlich hilfreicher als "top". – Couchy311

+0

Was ist es mit dem Beharren der Leute, dass die Erinnerung verschwendet wird? Freier Speicher macht * nichts * - es ist nicht besser als Speicher, der überhaupt nicht im Computer ist. Nur Speicher, der * in Gebrauch ist, tut etwas Gutes. –

Antwort

6

Dies ist eine spezifische Verwendung des Befehls top, nicht der std::vector. Das Problem besteht darin, dass der von Datenstrukturen freigegebene Speicher nicht an das Betriebssystem zurückgegeben wird, dh die Ebene, auf der der Befehl top die Speicherbelegung überwacht. Der Speicher, den das Betriebssystem Ihrem Programm gegeben hat, bleibt bei Ihrem Programm, bis der Speichermanager von C++ entscheidet, dass es Zeit ist, etwas Speicher zurück an das Betriebssystem zu geben.

Der Grund dafür ist, dass die Zuweisung von Speicher vom Betriebssystem relativ teuer ist, und es in relativ großen Brocken getan werden muss. Der Speichermanager der C++ - Laufzeitbibliothek ruft Speicher aus dem Betriebssystem "Großhandel" ab und verteilt ihn bei Bedarf an die Teile Ihres Programms.

Wenn Sie überprüfen möchten, ob der Speicher tatsächlich zurückgewonnen wird, verwenden Sie ein Tool, das die Speichernutzung auf einer niedrigeren Ebene überwacht, z. B. valgrind.

4

Auch wenn Sie den Speicher ordnungsgemäß freigeben, muss die Standardbibliothek den Speicher nicht wieder an das Betriebssystem freigeben.

Wenn Sie zum Beispiel zuerst den gesamten Speicher zuweisen, weist die Bibliothek dem OS eine Menge virtuellen Speicheradressraum zu (wahrscheinlich mit mmap(2)) und verteilt sie. Wenn Sie jedoch mit diesem Speicher fertig sind, hängt er unter der Annahme, dass Sie diesen Speicher möglicherweise später wieder haben möchten, an den virtuellen Adressraum, sodass er munmap(2) nicht aufruft, um den virtuellen Adressraum nicht zu mappen.

Daher, obwohl der gesamte Speicher ordnungsgemäß aus der Perspektive Ihres Programms befreit wurde, sieht das gesamte OS, dass Sie eine Menge virtuellen Speicher zugewiesen, aber dann nie freigegeben haben. Deshalb meldet top(1), dass Ihre Speicherauslastung nicht abnimmt, aber es ist nichts, worüber Sie sich Sorgen machen müssen. Wenn Ihr Programm erneut Arbeitsspeicher benötigt, wird es es aus dem virtuellen Adressraum reservieren, den Sie bereits haben, so dass Sie Ihre sichtbare Speicherauslastung nicht erhöhen werden, bis der gesamte Speicher aufgebraucht ist.

0

Wie in anderen Antworten angegeben, ist der Speicher für Ihren Prozess weiterhin verfügbar und wird nicht außerhalb davon freigegeben, bis das Programm beendet wird. Wenn Sie einen Allokator, der dies tun will, können Sie mit jemalloc auschecken, die es zurück auf das Betriebssystem freigibt und ist sehr nützlich in skalierbaren Multi-Threaded-Anwendungen wie Facebook aber wie bei allem gibt es andere Kosten.

Verwandte Themen