Partage
  • Partager sur Facebook
  • Partager sur Twitter

Pointeur non delete.

Sujet résolu
    26 novembre 2019 à 0:05:06

    Salut!

    Je voudrais delete un pointeur lorsque le joueur se déconnecte, je fais donc ceci :

    void MyAppli::onDisconnected(User* user) {
            std::vector<Entity*> heroes = World::getEntities("E_HERO");
            for (unsigned int i = 0; i < heroes.size(); i++) {
                if (user == static_cast<Hero*>(heroes[i])->getUser()) {
                    World::deleteEntity(heroes[i]);
                }
            }
            heroes = World::getEntities("E_HERO");
            if (heroes.size() == 1)
                std::cout<<"heroes!"<<std::endl;
        }

    Voici les méthodes pour delete (je delete les entités parents et les enfants)  :

    bool Map::deleteEntity (Entity *entity) {
                std::vector<Entity*> children = entity->getChildren();
                for (unsigned int i = 0; i < children.size(); i++) {
                    if (entity->isAnimated()) {
                        deleteEntity(static_cast<AnimatedEntity*>(children[i])->getCurrentFrame());
                        delete entity;
                    } else {
                        deleteEntity(children[i]);
                        delete children[i];
                    }
                }
                if (entity->isLeaf()) {
                    std::vector<Face*> faces = entity->getFaces();
                    for (unsigned int j = 0; j < faces.size(); j++) {
                        decreaseComptImg(faces[j]->getMaterial().getTexture());
                    }
                    gridMap->deleteEntity(entity);
                }
                
            }
    bool GridMap::deleteEntity (Entity *entity) {
    
                int x = entity->getGlobalBounds().getPosition().x;
                int y = entity->getGlobalBounds().getPosition().y;
                int endX = (x + entity->getGlobalBounds().getWidth());
                int endY = (y + entity->getGlobalBounds().getHeight());
                bool removed = false;
                for (int i = x; i <= endX; i+= offsetX) {
                    for (int j = y; j <= endY; j+= offsetY) {
                        math::Vec2f pos (i, j);
                        CellMap *cellMap = getGridCellAt(pos);
                        if (cellMap != nullptr) {
                          if(cellMap->removeEntity(entity) && !removed)
                            removed = true;
                          if (!cellMap->isEntityInside())
                                removeCellMap(cellMap);
                        }
                    }
                }
                delete entity;
                return removed;
            }
    bool CellMap::removeEntity (Entity *entity) {
                typename vector<std::unique_ptr<Entity>>::iterator it;
                for (it = entityInside.begin(); it != entityInside.end();) {
                    if (entity == it->get()) {
                        it->release();
                        it = entityInside.erase(it);
                        return true;
                    } else
                        it++;
    
                }
                return false;
            }



    Cependant l'entité n'est pas delete ni retiré du monde, la taille de mon vecteur vaut toujours un. Du coups je me retrouve avec l'id d'un joueur qui vient de se déconnecté et lorsqu'un autre veut se connecter ça plante. :pirate:

    C'est bon j'ai trouvé pourquoi, en fait, côté serveur l'entité caractère c'est une feuille, car il n'y a pas d'entités enfants côté serveur donc rien à afficher, donc je devais redéfinir la méthode isLeaf et renvoyer vrai du coup ça rentre dedans sinon ça ne rentrait pas dedans.


    -
    Edité par OmbreNoire 26 novembre 2019 à 0:39:43

    • Partager sur Facebook
    • Partager sur Twitter
      26 novembre 2019 à 9:57:19

      Déjà, utilise des smart pointers. On ne s'amuse pas à faire des new/delete manuellement. En particulier, ici std::unique_ptr. D'autant plus que tu utilises déjà des std::unique_ptr, pourquoi tu as encore un autre vector de pointeurs bruts ?

      Passe en pas à pas au debugger pour voir ce qu'il coince.

      Autre chose, le fait de devoir faire des static_cast vers le bas semble indiquer une erreur de conception je pense.

      • Partager sur Facebook
      • Partager sur Twitter

      git is great because Linus did it, mercurial is better because he didn't.

        27 novembre 2019 à 20:32:07

        Le problème avec std::unique_ptr c'est qu'il faut qu'il soit détruit pour que son contenu soit supprimé, là j'ai besoin de faire un delete lors d'un évènement. (La déconnexion d'un joueur), je dois donc le faire manuellement.

        Je préfère faire un static_cast vers le bas plutôt que de mettre des méthodes supplémentaire et virtuelles dans la classe mère Entity (qui en contient déjà plein d'ailleurs), c'est un choix, pas une erreur.

        • Partager sur Facebook
        • Partager sur Twitter
          27 novembre 2019 à 20:44:57

          Bonsoir

          Si tu utilises la fonction membre 'reset()' sans paramètres avant l'appel implicite du destructeur (comprendre avant la fin de porté du unique_ptr), la ressource du unique_ptr est détruite.

          • Partager sur Facebook
          • Partager sur Twitter

          Mon site web de jeux SDL2 entre autres : https://www.ant01.fr

            28 novembre 2019 à 8:56:53

            OmbreNoire a écrit:

            Je préfère faire un static_cast vers le bas plutôt que de mettre des méthodes supplémentaire et virtuelles dans la classe mère Entity (qui en contient déjà plein d'ailleurs), c'est un choix, pas une erreur.

            Ça malheureusement c'est le problème des “God objects”

            • Partager sur Facebook
            • Partager sur Twitter

            git is great because Linus did it, mercurial is better because he didn't.

              29 novembre 2019 à 8:51:24

              Ou alors tu stocks les smarts-pointer représentants tes joueurs dans un conteneur et tu détruits l’enregistrement (via un mes_joueurs.erase(n) par exemple) quand ton joueur n se déconnecte, ce qui appelera automatiquement le destructeur du smart-pointer.


              Pour info, les new et les delete ne doivent être presents respectivement que dans les constructeurs et destructeurs, et il doit y en avoir qu'une seule pair par classe. Si ce n'est pas le cas, repenses ton code ou utilise les smart-pointer qui reprennent ce principe (RAII).

              -
              Edité par ChristopheDrieu1 29 novembre 2019 à 9:13:31

              • Partager sur Facebook
              • Partager sur Twitter

              Pointeur non delete.

              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
              • Editeur
              • Markdown