2011-01-05 1 views
1

J'apprends un peu de C++ par moi-même, et je ne suis pas entièrement sûr d'avoir une bonne compréhension de la gestion de la mémoire. Je ne connais que Java et un peu de PHP et de Python, donc c'est un peu nouveau pour moi. Je travaille également avec SDL - cela m'a semblé un moyen intéressant d'accélérer le processus d'apprentissage. Quoi qu'il en soit, j'essaye d'écrire une fonction de nettoyage qui libère toutes les surfaces qui ont été passées à une pile (j'utilise simplement la pile STL). Donc, j'ai le code suivant (abrégé):L'apprentissage de C++ et SDL- génère-t-il une fuite de mémoire?

#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(); 

Je ne suis pas sûr de la méthode de nettoyage. Je pensais que ce serait une meilleure façon d'implémenter la fonction SDL_FreeSurface plutôt que de spécifier manuellement chaque surface. Donc, si j'ai dessiné dix images à l'écran (disons dix vaisseaux) et que je les ai fait exploser, je devrais les supprimer correctement. Je créerais une pile pour ces 10 vaisseaux, et après leur destruction, je pourrais tout effacer, si cela avait du sens. Je suis inquiet que je complique trop les choses et introduit une toute nouvelle façon de causer des fuites de mémoire.

Des commentaires/remarques seraient les bienvenus! Je suis nouveau en C++ alors n'hésitez pas à me moquer de ma tentative futile de gestion de la mémoire.

Répondre

2

Votre propre code n'a aucune fuite de mémoire. En supposant que load_image() est sûr aussi, le code entier est propre des fuites de mémoire.

Rappelez-vous que, si vous n'utilisez pas l'opérateur new, aucune fuite de mémoire se produit.

+0

Vous pouvez reformuler votre seconde phrase. Rappelez-vous que si vous n'utilisez pas le nouvel opérateur, aucune fuite de mémoire ne se produit car il n'est pas vrai que le nouvel opérateur ne générera pas de fuites de mémoire. – ForceMagic

1

Il est un peu déroutant ce que vous faites, mais, si SDL_FreeSurface() libère l'objet (???), alors je ne vois pas une fuite de mémoire.

Qu'essayez-vous de faire? Que fait SDL_FreeSurface()? Que fait load_image() et comment alloue-t-il la mémoire si c'est le cas?

+0

SDL_FreeSurface supprime la surface incluse dans SDL. load_image affecte plus ou moins une image (à partir d'un fichier) à un écran en utilisant des pointeurs (dans ce cas, il pointe vers une surface). Il définit également une clé de couleur et supprime les pixels de cette couleur pour obtenir la transparence. J'essaie juste de trouver un système de collecte des ordures pour les surfaces, rien de vraiment compliqué. J'essaie juste d'éviter toute fuite de mémoire possible, mais il semble que je sois en clair (pour l'instant). – thomascirca

+0

à quoi ressemble? Quoi qu'il en soit, le fait est que vous ne semblez pas avoir de fuite de mémoire dans votre code mais, encore une fois, votre code n'alloue ou ne libère aucune mémoire. Vraisemblablement, load_image() et SDL_FreeSurface() le font. En supposant que tout va bien, alors ça devrait aller. Je pourrais changer votre boucle while pour ne contenir que 'SDL_FreeSurface (surfaces.pop())' comme fonction de sécurité pour garantir que la mémoire libérée n'est toujours pas stockée. –

+0

Désolé - il semble que je n'ai pas de problème de fuite de mémoire. J'aime l'idée du changement de boucle - je vais essayer plus tard. Merci! – thomascirca

1

Cela ne semble pas avoir de fuites de mémoire. Cependant, vous voulez vous assurer que vous ne gardez pas les surfaces trop longtemps, ou il peut sembler que vous avez des fuites (la même chose peut se produire en Java). En supposant que clean est appelé assez souvent, vous devriez aller bien. Ceci déplace le problème de nettoyage des surfaces individuelles (en appelant SDL_FreeSurface au moment approprié) pour nettoyer la pile de surfaces (en appelant clean au moment opportun). Si vous avez déjà du code (ou une idée) en place pour gérer la pile, je vais aller de l'avant et courir avec. Si ce n'est pas le cas, j'essaierais de trouver un moyen de gérer les durées de vie des surfaces individuellement, car cette approche est plus flexible et n'introduit pas un nouveau concept.

+0

Merci pour la réponse! J'ai quelques idées sur la gestion de la pile, mais je ne l'ai pas encore implémenté. – thomascirca

0

avoir une lecture à propos RAII - C++ est très bon. Une fois que vous comprenez ce qui se passe (en gros, c'est l'allocation des ressources dans le constructeur et la désallocation dans le destructeur - ce qui signifie que vos objets se nettoient) - vous pouvez créer de belles enveloppes pour les fonctions SDL. Voici comment vous feriez une surface:

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

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

où m_pSurface est une variable membre de type SDL_Surface *.

Dans le monde parfait que vous voudriez faire cette classe incopiable, gérer le constructeur de déplacement si vous utilisez C++ 0x et vérifier les codes d'erreur et lancer des exceptions. Mais cela devrait vous aider à démarrer.

0

La meilleure façon de détecter les fuites de mémoire est d'utiliser valgrind. Pour autant que je sache, cela ne fonctionne que sur linux, mais il vaut vraiment la peine d'étudier et d'utiliser.