2011-10-05 1 views
0

J'essaie de trouver une fuite de mémoire avec le détecteur visuel de fuite. Il me montre m_neighbors.push_back(ent); provoque une fuite.push_backing dans la liste des pointeurs provoque une fuite de mémoire

(brève callstack = NeighborCalculatorDummy -> foreach -> Liste -> allouer)

Je l'utilise comme NeighborCalculatorDummy<Entity *>, donc il suffit d'insérer repoussage doit pointer dans la liste sans aucune allocation. Tous les pointeurs vers des entités qui proviennent d'addEntity sont supprimés ailleurs dans le code ...

Comment est-il possible que push_back provoque une fuite?

template <typename entity_type> 
class NeighborCalculatorDummy 
{ 
public: 
    inline void addEntity(const entity_type & entity) 
    { 
     m_entities.push_back(entity); 
    } 

    void calculateNeighbors(const vector_type & position, flt32 radius) 
    { 
     flt32 rSq = radius*radius; 
     m_neighbors.clear(); 

     std::for_each(m_entities.begin(), m_entities.end(), [&](entity_type ent){ 
      if(lengthSq(ent->getPosition() - position) <= rSq) 
       m_neighbors.push_back(ent); 
     }); 
    } 

private: 
    std::vector<entity_type> m_entities; 
    std::list<entity_type> m_neighbors; 
}; 

modifier

ici est le code autour NeighborCalculator

//#1 
std::list<Vehicle *> vehicles; 
vehicles.push_back(new Vehicle); 
vehicles.push_back(new Vehicle); 
vehicles.push_back(new Vehicle); 

//#2 
NeighborCalculatorDummy<Vehicle *> neighborCalculator = new NeighborCalculatorDummy<Vehicle *>(); 

std::for_each(vehicles.begin(), vehicles.end(), [&](Vehicle * vehicle){ 
    neighborCalculator->addEntity(vehicle); 
}); 

//#3 impl of addEntity 
template <typename entity_type> 
void NeighborCalculatorDummy<entity_type>::addEntity(const entity_type & entity) 
{ 
    ... 
    m_entities.push_back(entity); //m_entities is - std::vector<Vehicle *> 
} 

//#4 end of program 
delete neighborCalculator; 

std::for_each(vehicles.begin(), vehicles.end(), [&](Vehicle * vehicle){ 
    delete vehicle; 
}); 
+0

Où supprimez-vous le pointeur avec de la mémoire allouée dynamiquement? Où l'avez-vous alloué? –

+0

Vous avez probablement besoin d'ajouter plus d'informations, comme quel est le type de 'entity_type', et comment le' NeighborCalculatorDummy' est utilisé (est-il détruit?) Si la mémoire qui a fui a été acquise dans l'appel 'push_back', semble indiquer que la liste n'est pas détruite correctement. –

+0

Le détecteur de fuite de mémoire CRT indique-t-il la même fuite? –

Répondre

0

J'ai omis le destructeur virtuel dans le parent de l'entité. C'est pourquoi le repousser a provoqué une fuite.

1

Il me semble que entity_type est un pointeur (à en juger de la for_each lambda).

Vous vouliez probablement utiliser

NeighborCalculatorDummy<SomeEntity> 

au lieu de

NeighborCalculatorDummy<SomeEntity*> 

dans un autre lieu de votre code (non représenté)

Bien sûr, le lambda serait alors orthographié différemment:

[&](const entity_type& ent){ 
     if(lengthSq(ent.getPosition() - position) <= rSq) 
      m_neighbors.push_back(ent); 
    } 

et peut-être plus de points similaires qui supposaient le type de entity_type nécessaire de déréférencement.

Sinon, vous pouvez utiliser

  • vector<std::shared_ptr<entity_type> > au lieu
  • Boost pointeur conteneurs

Ces pourrait être plus approprié lorsque vos entités sont des types polymorphes ou non copyables/biens meubles. Cependant, il est également probable que plus de travail pour changer votre code autour de

+0

Alors qu'il pourrait être possible que l'utilisateur veuille cette version différente, cela n'explique pas la fuite de mémoire. Ce n'est pas l'objet 'SomeEntity' celui qui n'est pas désalloué, mais plutôt le noeud list (qui est ce qui est acquis à partir de' allocator' dans 'push_back') –

+0

+1 pour le std :: shared_ptr –

+0

Je ne sais pas vouloir l'utiliser comme 'NeighborCalcDummy ' parce qu'il créerait la liste des autres entités dans 'NeighborCalcDummy'. Je veux travailler seulement avec des pointeurs avec cette classe (puisque stl ne permet pas de créer vecotr/liste de références) – relaxxx

0

Avec cette définition, en fonction de entity_type, le code fuira ou non.

  • Si entity_type est un pointeur, le destructeur par défaut appellera simplement le destructeur de vecteur. Cela libèrera la mémoire allouée à ces pointeurs, mais n'appellera pas la suppression. Si cette classe "possède" les éléments à l'intérieur du vecteur et doit les libérer, vous devez ajouter un destructeur qui appelle la suppression pour tous les éléments à l'intérieur du vecteur. Dans ce cas, vous pourriez penser au paramètre du template et ne pas préciser qu'un pointeur est nécessaire ici.
  • Si entity_type est un type de valeur, le destructeur par défaut est suffisant car les copies placées dans le vecteur seront supprimées par le destructeur du vecteur.
Questions connexes