2010-04-08 6 views
0

J'utilise Visual Studio 2008, Développement d'une fenêtre OpenGL. J'ai créé plusieurs classes pour créer un squelette, un pour les articulations, un pour la peau, un pour un corps (qui est un support pour plusieurs articulations et peau) et un pour lire un fichier skel/skin.Fuite de mémoire C++, Impossible de trouver où

Dans chacune de mes classes, j'utilise des pointeurs pour la plupart de mes données, dont la plupart sont déclarées en utilisant = new int [XX]. J'ai un destructeur pour chaque classe qui supprime les pointeurs, en utilisant delete [XX].

Dans ma fonction d'affichage GLUT, je l'ai déclaré un corps, ouvrir les fichiers et les dessiner, puis supprimer le corps à la fin de l'affichage. Mais il y a toujours une fuite de mémoire quelque part dans le programme. À mesure que le temps passe, l'utilisation de la mémoire continue d'augmenter, à un rythme constant, que j'interprète comme quelque chose qui n'est pas supprimé.

Je ne sais pas si c'est quelque chose dans la fonction d'affichage glut qui ne supprime pas la classe Body, ou quelque chose d'autre. J'ai suivi les étapes pour la détection de fuite de mémoire dans Visual Studio 2008 et il ne signale aucune fuite, mais je ne suis pas sûr à 100% si cela fonctionne bien pour moi. Je ne parle pas couramment le C++, donc il y a peut-être quelque chose que je néglige, quelqu'un peut-il le voir?

De principale:

void display(void){ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    Body *body = new Body(); 
    body->readSkel("C:\\skel2.skel"); 
    body->drawBody(); 
    body = new Body(); 
    body->readSkel("C:\\skel1.skel"); 
    body->drawBody(); 
    glutSwapBuffers(); 
    body->~Body(); 
    delete body; 
} 

De corps:

Body::Body(){ 
    skelFile = string(); 
    skinFile = string(); 
    totalJoints = 0; 
    joints = new Joint[25]; 
    skin = new Skin; 
} 

Body::~Body(){ 
    delete[25] joints; 
    delete skin; 
} 
+7

S'il vous plaît arrêtez de coder et lisez Effective C++ 3e édition de Scott Meyers Je ne veux pas être sarcastique, mais je suis tenté de créer une réponse longue juste adresser certains de vos erreurs de codage et mauvaises pratiques.Le livre de Scott Meyers vous mettra sur la bonne voie pour mieux coder. Ular article 4 et 14. –

+0

Will do. Désolé, ça fait longtemps que je n'ai pas fait de C++, notre école n'enseigne désormais que Java (sucks, non?) Et le professeur nous oblige à utiliser C/C++ sans nous montrer quoi que ce soit d'abord. I <3 Académie. – Nicholas

Répondre

6

Dans ce code:

Body *body = new Body(); 
body->readSkel("C:\\skel2.skel"); 
body->drawBody(); 
body = new Body(); 

vous fuit un Body parce que vous ne supprimez pas le premier.

Et ceci:

body->~Body(); 
delete body; 

est juste bizarre. Vous n'appelez pas explicitement les destructeurs comme ça - le delete prend soin d'appeler le destructeur.

Ce code:

delete[25] joints; 

est aussi bizarre. La position correcte est:

delete [] joints; 

Vous utilisez une syntaxe non standard, et la 25 sera ignorée. Voir this question pour plus d'informations.

+0

Mon diable, je les échangeais dans mon code et j'en avais effectivement un commenté ... et ça marche, je vois ce que j'ai fait là ... Merci beaucoup. – Nicholas

+0

L'appel de destructeur supplémentaire pour le corps entraînera probablement une double suppression des articulations et de la peau - Je suis surpris que cela ne s'est pas écrasé. –

+0

@RichieHindle - 'body-> ~ Body(); delete body' n'est pas seulement bizarre mais pourrait causer un comportement indéfini dans son exemple. Le destructeur sera appelé deux fois et puisque son code ne place pas 'joints' ou' skin' à 0, le code va double supprimer ce qui peut causer UB. –

1

Il serait utile si vous coller dans un petit code, mais je:

Vérifiez votre syntaxe: int * foo = new int [taille]; supprimer [] foo;

Assurez-vous que toutes les classes enfants dont les parents utilisent la mémoire dynamique contiennent également des destructeurs, même si le destructeur est une instruction vide.

+0

Le code est listé ci-dessous. Je me suis assuré que pour chaque nouveau, j'ai une suppression. – Nicholas

+0

peut-être que je n'ai pas eu assez de café ce matin, mais je vois deux nouvelles instructions Body() allouer de la mémoire, mais seulement un appel au destructeur. Qu'arrive-t-il à ton premier corps? –

3

Les vrais programmeurs peuvent écrire Fortran Java dans n'importe quelle langue! Java nécessite que vous allouiez (pratiquement) tout de façon dynamique, mais pas C++.

Puisque personne d'autre ne l'a souligné (au moins directement), dans display il ne semble y avoir aucune raison d'utiliser l'allocation dynamique du tout. Il suffit de faire quelque chose comme:

void display(void){ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    Body body; 
    body.readSkel("C:\\skel2.skel"); 
    body.drawBody(); 

    Body body2; 
    body2.readSkel("C:\\skel1.skel"); 
    body2.drawBody(); 
    glutSwapBuffers(); 
} 

Si votre readSkel efface les données de squelette existantes, vous n'avez pas besoin de définir body2, mais sans savoir que, c'est le moyen facile de garder les choses en toute sécurité.

De même, dans votre définition de Body, vous ne semblez pas non plus faire quoi que ce soit qui nécessite une allocation dynamique.

class Body { 
    std::string skelFile; 
    std::string skinFile; 
    int totalJoints; 
    Skin skin; 
    Joint joints[25]; 
public: 
    Body() : totalJoints(0) {} 
}; 

ou mieux encore:

class Body { 
    std::string skelFile; 
    std::string skinFile; 
    Skin skin; 
    std::vector<Joint> joints; 
public: 
    // presumably other stuff goes here...but you don't need a ctor or dtor. 
}; 

Cela se débarrasse de la plupart des chances de quoi que ce soit une fuite (au moins dans ces parties du code - puisque nous avons pas vu votre peau ou des classes mixtes, Il est difficile de deviner ce qu'ils peuvent faire ...

+0

Yup, super conseil. N'utilisez pas l'allocation dynamique, sauf si vous devez le faire. – jalf