IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Problème d'allocation dynamique


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    80
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 80
    Par défaut Problème d'allocation dynamique
    Bonjour, bonsoir,

    J'ai commencé depuis quelques temps la création d'un moteur physique 2D, j'ai donc crée mes différentes classes et autres.

    Le moteur physique est composé de formes basiques ( Bloc, triangle, cercle ).
    Chaque forme hérite de la classe "Listener" qui elle contient les informations nécessaires à tester les collision et autres ( Force, Velocité, position, ...).

    La classe "Listener" contient aussi un pointeur appellé m_vertices, celui-ci sert à allouer dynamiquement par la suite les sommets des polygons.
    Exemple : Je crée un objet de type "Cercle", je choisis le nombre de points que le cercle possedera puis celui-ci se crée.

    Malheuresement cette partie la pose problème, Si je crée un premier cercle, celui-ci fonctionne correctement. Des que je souhaite en crée un autre, le programme plante, ou celui-ci se lance mais le second cercle à un point en moins.

    Voici un screen montrant le problème :



    Le second cercle ressemble plus à pacman et le programme plante à sa fermeture.
    Je ne voit pas du tout d'ou ça vient, a chaque nouvel objet crée ( apres un premier ), les suivant on un sommet en moins ( Le premier du tableau j'ai l'impression ( m_vertices) ).

    Voici le code source du moteur ( Inclus un programme de test ) :
    Télécharger depuis un client SVN : svn checkout http://hx-engine.googlecode.com/svn/trunk/ hx-engine-read-only
    Télécharger archive .rar : Voir le Fichier : hxengine_l6yxj7gfr7.rar

    L'allocation se fait dans les classes du dossier "Formes".
    J'ai inclus un programme d'exemple avec. ( Dans le dossier "Exemple" )

    Merci à vous.
    Hybrix.

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Salut,

    Tu dérives des classes de Listener alors qu'elle n'a aucune méthode virtuelle : déclare le destructeur virtuel :
    Ensuite ta variable est de type :
    Donc est un pointeur sur un Vector, mais tu alloues la mémoire en faisant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    m_vertices = new Vector[m_verticesNumber];
    Donc comme un tableau de Vector...


    Sinon je pense que tu devrais lire quelques bouquins ou jeter un oeil à des tutoriels parce qu'il y a quelques trucs pas géniaux, dont :
    . il faut utiliser les listes d'initialisation dans les constructeurs
    . il faut libérer ce que tu alloues (si tu fais un new dans un constructeur il faut faire un delete dans le destructeur)
    . il vaut mieux utiliser des std::vector (par exemple) plutôt que des tableaux (en plus tu en utilises ailleurs)
    . il vaut mieux passer des const & plutôt que des copies sur les types autre que de base (genre Vector).
    . ça ne sert à rien de tester si un pointeur vaut 0 (ou NULL) avant de le delete (le test est de toute façon fait dans l'implémentation de delete)
    . ça ne sert à rien de remettre un pointeur à 0 (ou NULL) après l'avoir libéré dans un destructeur (à la fin du destructeur l'objet n'existe plus de toute façon)
    . il faut tester qu'un pointeur qui peut être nul ne l'est pas avant de la manipuler (cf. m_separationAxis dans Collision)
    . il faut faire gaffe aux fuites mémoires (m_separationAxis m'a l'air écrasé à chaque appel de Collision::Search)

    Après la conception est sans doute améliorable (cette classe Listener avec plein de données en protected avec leur tripotée d'accesseurs/mutateurs) mais c'est moins génant à la limite.

    MAT.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    80
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 80
    Par défaut
    Salut,

    Merci beaucoup d'avoir pris le temps de regarder les sources et d'avoir répondu à mon sujet ( Et en plus rapidement ), ça fait plaisir .

    J'ai suivi tes conseils dumoins certains :

    Tu dérives des classes de Listener alors qu'elle n'a aucune méthode virtuelle : déclare le destructeur virtuel :
    Je ne savais pas qu'il falait faire ça, je le faisait uniquement lorsque la classe était abstraite. Doit je le faire aussi pour les classes filles ?

    il faut utiliser les listes d'initialisation dans les constructeurs
    Le truc c'est que la liste vas être énorme pour certainnes classes ( cf. Listener.hpp), mais je l'ai fait pour les autres.

    . il vaut mieux utiliser des std::vector (par exemple) plutôt que des tableaux (en plus tu en utilises ailleurs)
    J'ai désormais enlever tout les tableaux et je suis passé sous les "vector", résultat : Le moteur ne plante plus et les problème d'affichages ont disparus.

    il vaut mieux passer des const & plutôt que des copies sur les types autre que de base (genre Vector).
    Je n'ai pas très bien compris cela, serait t-il possible d'avoir plus d'infos ?

    ça ne sert à rien de tester si un pointeur vaut 0 (ou NULL) avant de le delete (le test est de toute façon fait dans l'implémentation de delete)
    . ça ne sert à rien de remettre un pointeur à 0 (ou NULL) après l'avoir libéré dans un destructeur (à la fin du destructeur l'objet n'existe plus de toute façon)
    . il faut tester qu'un pointeur qui peut être nul ne l'est pas avant de la manipuler (cf. m_separationAxis dans Collision)
    . il faut faire gaffe aux fuites mémoires (m_separationAxis m'a l'air écrasé à chaque appel de Collision::Search)
    Les "vector" ont résolus ses soucis .

    Après la conception est sans doute améliorable (cette classe Listener avec plein de données en protected avec leur tripotée d'accesseurs/mutateurs) mais c'est moins génant à la limite.
    Je trouve cela très propre et offre pas mal de possibilitée à l'objet.

    Merci encore d'avoir répondu.

  4. #4
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Citation Envoyé par Hybrix Voir le message
    Je ne savais pas qu'il falait faire ça, je le faisait uniquement lorsque la classe était abstraite. Doit je le faire aussi pour les classes filles ?
    Plus d'information sur les destructeurs virtuels dans la FAQ.
    Sinon en théorie non il n'est pas nécessaire de remettre le mot clef virtual dans la classe fille ("virtuelle un jour, virtuelle toujours"), mais en général on le fait quand même par soucis d'homogénéité parce que pour une méthode 'normale' on le remet systématiquement pour éviter qu'un utilisateur d'une classe fille n'ait besoin d'aller voir dans la classe mère si par hasard la méthode est virtuelle ou non.

    Citation Envoyé par Hybrix Voir le message
    Le truc c'est que la liste vas être énorme pour certainnes classes ( cf. Listener.hpp)
    Je ne vois pas très bien le rapport, tu n'es pas obligé d'y mettre les initialisations par défaut (un std::vector typiquement).
    Si tu trouves que la liste est trop longue c'est sans doute qu'il y a trop de données dans une classe...
    C'est juste que plutôt qu'initialiser dans le corps du constructeur il faut faire la même chose dans la liste d'initialisation, la différence en terme de volume de code est minime...
    De nouveau des informations sur ce point dans la FAQ.

    Citation Envoyé par Hybrix Voir le message
    Je n'ai pas très bien compris cela, serait t-il possible d'avoir plus d'infos ?
    Plutôt que de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void Listener::AddForce(Vector force)
    {
      ...
    }
    Il vaut mieux faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void Listener::AddForce(const Vector& force)
    {
      ...
    }
    Ca évite une copie.
    Pour Vector c'est sans doute négligeable puisqu'il n'est composé que de 2 float, mais par soucis d'homogénéité on le fait en général pour tous les types qui ne sont pas de base.

    MAT.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    80
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 80
    Par défaut
    Merci beaucoup pour ces précisions, mes problèmes sont résolus.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème d'allocation dynamique
    Par adc15 dans le forum C
    Réponses: 3
    Dernier message: 09/02/2010, 10h48
  2. Réponses: 3
    Dernier message: 20/09/2009, 17h40
  3. problème d'allocation dynamique.
    Par watiero dans le forum C++
    Réponses: 15
    Dernier message: 18/02/2008, 18h06
  4. Problème d'allocation dynamique
    Par addsomemusic dans le forum Fortran
    Réponses: 3
    Dernier message: 11/01/2008, 10h45
  5. Question sur les problèmes d'allocation dynamique
    Par slylafone dans le forum C++
    Réponses: 23
    Dernier message: 25/10/2004, 14h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo