Speicher freigeben



  • Hallo, ich habe mal eine Frage zu folgendem Code. Ich in der Methode read() die Zeilen aus einer Datei ein und speichere sie in einer Liste. Am Schluß gebe ich die Liste dereferenziert zurück. Wenn ich das so mache wie es da steht wird dann der Speicher für die in read() allokierte Liste überhaupt wieder freigegeben? In der Methode selbst geht das ja nicht. Gruß

    list<string> read()
    {
    	char buffer[255];
    
    	ifstream file("lines.txt");
    
    	list<string>* strings = new list<string>();
    	string line;
    
    	while (file.good()) {
    		file.getline(buffer, 255);
    		line = buffer;
    		strings->push_back(line);
    	}
    
    	file.close();
    	return *strings;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	list<string> commands = read();
    
    	system("pause");
    	return 0;
    }
    


  • Gast213 schrieb:

    list<string> read()
    {
    	char buffer[255];
    
    	ifstream file("lines.txt");
    	
    	list<string>* strings = new list<string>();
    	string line;
    
    	while (file.good()) {
    		file.getline(buffer, 255);
    		line = buffer;
    		strings->push_back(line);
    	}
    
    	file.close();
    	return *strings;
    }
    

    Wozu legst Du die Liste mit new an? Hast Du vorher Java programmiert? Besser ist es, Container auf den Stack zu packen:

    list<string> read()
    {
    	//char buffer[255]; braucht man nicht
    
    	ifstream file("lines.txt");
    
    	list<string> strings; //auto variable
    	string line;
    	//besser so:
    	while (std::getline(file, line, '\n'))
    	{
    		strings.push_back(line);
    	}
    
    	file.close();
    	return strings;
    	//hier stirbt das lokale strings. man muss sich um nichts kuemmern
    }
    


  • Ah, so gefällt mir das schon besser. Ja komme von Java 🙂 Bin mir noch unsicher wann Heap und wann Stack. Ich dachte Listen müsste ich auf den Heap packen wenn die Länge unbekannt ist. Und die getline Funktion kannte ich schlichtweg nicht. Danke



  • Achja, den Filestream musst Du auch nicht closen. Das passiert ebenfalls, wenn das ifstream Objekt beim Verlassen Deiner Funktion zerstört wird.



  • zu mal bei dir ein potenzielles speicherleck lauert bzw auch vorhanden sein wird zu jedem new gehört ein delete benuz dann lieber shared_ptr oder andere smart pointer http://www.c-plusplus.net/forum/viewtopic-var-t-is-134971.html



  • Kann man grob sagen wann man

    new
    

    benutzen sollte?



  • Gast213 schrieb:

    Kann man grob sagen wann man

    new
    

    benutzen sollte?

    Wenn (unvollständig und ungeordnet):
    - der Stack zu klein wird
    - der Speicher "scopeübergreifend" benötigt wird
    - spezielle Speicherverwaltungsmechanismen genutzt werden sollen (eigener Allocator, ...)
    - ...

    Ich würde sagen: Eigentlich nur in gezielten Ausnahmesituationen... Ich selbst fahre relativ gut mit Stackobjekten (bzw. "auto-Variablen") und benötige so gut wie NIE new.

    Gruß,

    Simon2.



  • zu jedem new sollst bzw muss du, wenn du "rohe" Pointer nimmst ein delete nutzen
    jeder speicher den du anforderst muss auch wieder freigeben werden (was dir schwer fällt, wenn du keinen passenden pointer,der drauf zeigt hast dann räumt normal dein betriebssystem nach porgramm ende auf)
    smart pointer haben den vorteil du kannst speicher anfordern und sobald der\die Pointer nicht mehr drauf zeigen wird diese objekt automatisch freigegeben


  • Administrator

    Gast213 schrieb:

    Ich dachte Listen müsste ich auf den Heap packen wenn die Länge unbekannt ist. Und die getline Funktion kannte ich schlichtweg nicht. Danke

    Das gilt nur für "normale" Arrays (oder auch C-Array genannt):

    void foo(int size)
    {
      int stackArray[255]; // Grösse ist zur Compilezeit bekannt, kann auf den Stack.
      int* heapArray = new int[size]; // Grösse ist erst zur Laufzeit bekannt, auf den Heap.
    
      delete[] heapArray; // nicht vergessen ;)
    }
    

    (Wobei natürlich jetzt jemand einwerfen könnte, dass es Heap und Stack in C++ gar nicht gibt, aber normalerweise wird es vom Betriebsystem/Compiler so gehandhabt :))

    std::list ist eine Klasse und das Objekt von so einer Klasse kannst du dort hin setzen, wo du es gern möchtest. std::list benutzt intern einen Allocator um den Speicher für die Elemente zu verwalten und per Default wird intern für die einzelnen Objekte new benutzt. Gleiches gilt auch für die anderen Container aus der Standardbibliothek.
    Deklaration von std::list und co:

    namespace std {
    
      template<typename T, typename Allocator = allocator<T>>
      class list
      {
        // ...
      };
    
    } // std
    

    Gast213 schrieb:

    Kann man grob sagen wann man new benutzen sollte?

    Grundsätzlich dann, wenn du erst zur Laufzeit weisst, was für Speicher du benötigst.
    Zudem für Speicher, welcher über den Scope hinaus benötigt wird.
    Und schlussendlich für "grosse" Speicherblöcke. Man muss nämlich bedenken, dass der Stack nur ca. 1 - 4 MB gross ist. Und auf den Stack kommen meisten auch noch alle Funktionsaufrüfe und all das Zeug, man sollte also vorsichtig sein und ab mehreren Kilobytes Speicherblöcke lieber die Sache auf den Heap setzen. Aber eine Regel gibt es eigentlich nicht, das ist jedem selber überlassen.

    Grüssli



  • Das war hilfreich. Danke an euch alle 🙂



  • Dravere schrieb:

    ...
    Und schlussendlich für "grosse" Speicherblöcke....

    Das wird leider oft mißverstanden (wie auch hier) als "wenn ich mehr als 1-4MB habe, muss ich meine Variablen auf den Heap legen (und da selbst verwalten)".

    Selbst für große Datenmengen kann man "auf dem Stack/ohne new[] arbeiten" - eben mithilfe von Containern (die ihrerseits bei größeren Datenmengen den Heap nutzen).

    Gruß,

    Simon2.


Anmelden zum Antworten