Speicherproblem mit vector



  • Guten Tag,
    folgendes Problem beschäftigt mich leider bereits seit längerer Zeit:

    void testfunktion() {
    	vector<string> v;
    	int anzahl = 100000;
    	for( int i=0; i<anzahl; i++ ) {
    		v.push_back( "teststring" );
    	}
    	v.clear();
    }
    
    void main() {
    	printf( "start\n" );
    	system( "pause" ); // Hier wird der Arbeitsspeicher des Prozesses im Taskmanager abgelesen
    	testfunktion();
    	printf( "ende\n" );
    	system( "pause" ); // Hier wird der Arbeitsspeicher des Prozesses erneut im Taskmanager abgelesen - zeigt mehr (etwa 524 KB bei einer Anzahl von 100.000) als vorher an 
    	return;
    }
    

    Eigentlich ist der vector doch lokal in der Funktion auf dem Stack und müsste mit Beenden der Funktion den Speicher wieder freigeben (auch ohne das "clear()"). Dasselbe Problem tritt allerdings auf wenn sich der vector auf dem Heap befindet:

    void testfunktion() {
    	vector<string> * v = new vector<string>;
    	int anzahl = 100000;
    	for( int i=0; i<anzahl; i++ ) {
    		v->push_back( "teststring" );
    	}
    	v->clear();
    	delete v;
    }
    

    Bei beiden Versionen sind es bei 100k Strings immer 524 KB, die nicht freigegeben werden! Besteht das Problem darin, dass sich die vectoren nicht vollständig löschen?

    void testfunktion() {
    	string test;
    	int anzahl = 100000;
    	for( int i=0; i<anzahl; i++ ) {
    		test = test + static_cast<string>("teststring");
    	}
    }
    

    Das Beispiel zeigt, dass es selbst mit ganz normalen strings so ist. Mache ich grundsätzlich etwas falsch? Wo liegt das Problem, dass jede beliebige Speicherreservierung (Stack oder Heap) Spuren hinterlässt und auf Dauer den Arbeitsspeicher zumüllt?



  • robinlench schrieb:

    Wo liegt das Problem, dass jede beliebige Speicherreservierung (Stack oder Heap) Spuren hinterlässt und auf Dauer den Arbeitsspeicher zumüllt?

    Zumüllt?
    Was ist bei int anzahl = 1000000; und int anzahl = 10000000; ?
    Verliert er da immer mehr Speicher? Oder sind die 528k einfach nur die geringe Grundlast?



  • anzahl    Speicher in KB
          100     20
        1.000    136
       10.000    524
      100.000    524
    1.000.000    932
    

    Bei 10 mio wird der Speicher während der Schleife über meinen Kapazitäten überlastet. Aber wie man sieht hängen die Speicherreste von der Anzahl ab.

    Was bedeutet Grundlast? Der Speicherverbrauch zum Start des Programms ist ein Wert, den ich von dem gemessenen Wert nach der Funktion subtrahiere. Dadurch kommen die o.g. Messwerte zustande. Es ist der zusätzliche Speicher, den die Funktion hinterlässt (während der Laufzeit liegt der Verbrauch bei deutlich mehr, es werden also Dinge gelöscht mit Ende der Funktion, aber eben nicht alles).

    Ich möchte mit dem Ende der Funktion nichts mehr mit diesen Objekten zu tun haben und diese aus dem Speicher vollständig entfernen. In meinem vollständigen Programm werden ja nicht nur solch kurze strings, sondern viele andere Objekte verwendet und da liegen die "Speicherreste" in nicht mehr vernachlässigbaren Dimensionen.

    Am Rande vielleicht noch, dass der Compiler der von Visual Studio 10 ist.



  • Ich kann im Taskmanager absolut keine Änderung des Speicherverbrauchs nachvollziehen.

    Kompiliert in einem frischen Projekt mit VS2010 und folgenden Kompileroptionen:

    /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Gm- /EHsc
    /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fp"Release\bla.pch" /Fa"Release\" /Fo"Release\" /Fd"Release\vc100.pdb" 
    /Gd /analyze- /errorReport:queue
    

    Egal wieviele Elemente ich verwende, der Speicherverbrauch zwischen vorher und nachher ist (im Taskmanager!) genau identisch.



  • new holt sich Speicher vom Betriebssystem. Und delete gibt Speicher auch wieder ans BS zurück.
    Aber new holt sich große Brocken vom BS und gibt sie als z.B. kleine Strings an Dein Programm weiter.
    delete gibt nicht sofort ohne Not alles zurück, das wäre sonst viel viel zu lahm. Daß wenigstens ein Block nicht zurückgegeben wird, damit muß absolut gerechnet werden. Daß der oder die am Ende noch allokierten Blöcke 932k groß sind, überrascht mich. Aber naja, zwischwendurch hattest Du Gigabyteweise Speicher gehabt. Vielleicht Log-Infos im Debug-Heap.

    Gäbe es ein Speicherloch, so daß je länger das Programm läüft, desto mehr Speicher verschwindet, das wäre fatal.

    Das Loch müßte man sehen mit:

    for(;;)
      testfunktion();
    

    und im Taskmanager müßte sichtbar sein, daß der SPeicher langsam alle wird.


Log in to reply