2011-01-05 9 views
1

Ich lerne ein bisschen C++ selbst, und ich bin mir nicht ganz sicher, ob ich das Speichermanagement gut beherrsche. Ich kenne nur Java und ein bisschen PHP und Python, also ist das ein bisschen neu für mich. Ich arbeite auch mit SDL - es schien eine interessante Möglichkeit zu sein, den Lernprozess zu beschleunigen. Wie auch immer, ich versuche, eine Aufräumfunktion zu schreiben, die alle Oberflächen freigibt, die an einen Stapel übergeben wurden (ich benutze nur den Stapel STL). Also, ich habe den folgenden Code (kurz):Lernen von C++ und SDL - erzeugt das folgende ein Speicherleck?

#include <stack> 

//stack of SDL_Surfaces 
stack<SDL_Surface*> surfaces; 

void clean() {  
    SDL_Surface *temp = NULL; 

    //loops through the stack depending on its size 
    while (surfaces.size() != 0) { 
     temp = surfaces.top(); 
     SDL_FreeSurface(temp); 
     surfaces.pop(); 

    } //while 
    if (surfaces.size() == 0) { 
     cout << "cleanup worked correctly" << endl;  
    } //if 
} 

//loading an image (this is in the main function) 
background = load_image("background.bmp"); 
surfaces.push(background); 

//cleaning time 
clean(); 

Ich bin nicht sicher über die Bereinigung Methode. Ich dachte, dies wäre ein besserer Weg, die SDL_FreeSurface-Funktion zu implementieren, anstatt jede Oberfläche manuell zu spezifizieren. Wenn ich also zehn Bilder auf den Bildschirm zeichne (sprich zehn Raumschiffe) und sie dann in die Luft sprenge, müsste ich sie richtig löschen. Ich würde für diese 10 Raumschiffe einen Stapel erstellen, und nach ihrer Zerstörung könnte ich sie alle vernichten, wenn das Sinn macht. Ich mache mir Sorgen, dass ich die Dinge übermäßig kompliziert habe und eine völlig neue Methode eingeführt habe, um Speicherlecks zu verursachen.

Jede Rückmeldung/Kommentar würde sehr geschätzt werden! Ich bin neu in C++ und verspotte meinen vergeblichen Versuch der Speicherverwaltung.

Antwort

2

Ihr eigener Code weist keine Speicherverluste auf. Wenn man davon ausgeht, dass load_image() auch sicher ist, ist der gesamte Code von Speicherlecks sauber.

Denken Sie daran, dass kein Speicherverlust auftritt, wenn Sie den Operator new nicht verwenden.

+0

Sie möchten vielleicht den zweiten Satz umformulieren _Bedenken Sie, dass, wenn Sie den neuen Operator nicht verwenden, kein Speicherverlust auftritt. Da es nicht wahr ist, dass der neue Operator keine Speicherverluste erzeugt, es sei denn, Sie rufen danach delete auf. – ForceMagic

1

Es ist ein wenig verwirrend, was Sie tun, aber, wenn SDL_FreeSurface() das Objekt (???) freigibt, dann sehe ich kein Speicherleck.

Was möchten Sie tun? Was macht SDL_FreeSurface()? Was macht load_image() und wie teilt es den Speicher zu, wenn es überhaupt funktioniert?

+0

SDL_FreeSurface löscht die Oberfläche, die als Teil von SDL enthalten ist. load_image weist einem Bildschirm ein Bild (aus einer Datei) mit Hilfe von Zeigern mehr oder weniger zu (in diesem Fall zeigt es auf eine Oberfläche). Es setzt auch einen Farbschlüssel und entfernt alle Pixel mit dieser Farbe, um Transparenz zu erreichen. Ich versuche nur ein Müllsammelsystem für Oberflächen zu entwickeln, nichts wirklich Kompliziertes. Ich versuche nur mögliche Speicherlecks zu vermeiden, aber es sieht so aus, als wäre ich im klaren (vorerst). – thomascirca

+0

Sieht aus wie was? Auf jeden Fall ist es so, dass Sie keinen Speicherleck in Ihrem Code haben, aber Ihr Code teilt oder befreit keinen Speicher. Vermutlich funktioniert load_image() und SDL_FreeSurface(). Vorausgesetzt, die sind in Ordnung, dann sollte es dir gut gehen. Ich könnte Ihre while-Schleife so ändern, dass sie nur 'SDL_FreeSurface (sources.pop()) 'als Sicherheitsfunktion enthält, um sicherzustellen, dass der frei gewordene Speicher nicht noch irgendwo gespeichert wird. –

+0

Es sieht so aus, als hätte ich kein Speicherleck. Ich mag die Idee über die Loop-Änderung - ich werde es später versuchen. Vielen Dank! – thomascirca

1

Dies scheint keine Speicherlecks zu haben. Sie möchten jedoch sicherstellen, dass Sie Oberflächen nicht zu lange herumliegen lassen oder dass es so aussieht, als hätten Sie Undichtigkeiten (dasselbe kann in Java passieren). Angenommen, dass clean oft genug aufgerufen wird, sollten Sie in Ordnung sein.

Dies verschiebt das Problem der Reinigung der einzelnen Oberflächen (durch den Aufruf SDL_FreeSurface zur entsprechenden Zeit) auf den Stapel der Oberflächen zu reinigen (durch den Anruf clean zur entsprechenden Zeit). Wenn Sie bereits Code (oder eine Idee) zum Verwalten des Stapels haben, würde ich weitermachen und damit laufen. Wenn nicht, würde ich versuchen, die Oberflächenlebensdauern individuell zu verwalten, da dieser Ansatz flexibler ist und kein neues Konzept einführt.

+0

Danke für die Antwort! Ich habe einige Ideen, wie ich den Stapel verwalten kann, aber ich muss ihn noch implementieren. – thomascirca

0

Lesen Sie mehr über RAII - C++ ist sehr gut darin. Sobald Sie verstehen, was passiert (im Grunde ist es Ressourcenzuweisung im Konstruktor und Aufhebung der Zuordnung im Destruktor - was bedeutet, dass Ihre Objekte sich selbst bereinigen) - können Sie nette Wrapper für die SDL-Funktionen erstellen. Hier ist, wie man eine Oberfläche tun würde:

CBitmapSurface::CBitmapSurface(const std::string &filename) 
{ 
    m_pSurface = SDL_LoadBMP(filename.c_str()); 
} 

CBitmapSurface::~CBitmapSurface() 
{ 
    SDL_FreeSurface(m_pSurface); 
} 

wo m_pSurface ist eine Membervariable vom Typ SDL_Surface *.

In der perfekten Welt möchten Sie diese Klasse nicht kopierbar machen, behandeln Sie den Move-Konstruktor, wenn Sie C++ 0x verwenden und Fehlercodes überprüfen und Ausnahmen auslösen. Aber das sollte dich beginnen.

0

der beste weg bei der Suche nach Speicherlecks ist Verwendung Valgrind. Soweit ich weiß, funktioniert es nur auf Linux, aber es lohnt sich die Zeit zu untersuchen und zu verwenden.