Question

J'ai un vecteur de pointeurs à une classe. Je dois appeler leurs et libérer leur Destructeurs mémoire. Puisqu'ils sont vecteur de pointeurs vector.clear () ne fait pas le job.So je suis allé à le faire manuellement comme ceci:

void Population::clearPool(std::vector<Chromosome*> a,int size)
{
    Chromosome* c;
    for(int j = 0 ;j < size-1;j++)
    {
       c = a.back();
       a.pop_back();
       delete c;
       printf("  %d \n\r",j);
       c = NULL;

    }

}

Le printf y est depuis que j'ai destructor parler pour voir où Chromosome la faute de segmentation se produit. Lorsque ClearPool () est appelée et dire que nous avons eu une taille de 100, il peut donner une erreur de segmentation dans une Chromosome entre 0 et 100.

Je ne sais pas pourquoi cela pourrait se produire et je n'ai un moyen de réellement trouver ce qui ne va pas depuis lors du débogage avec tout ce que je vois des points d'arrêt est qu'il se produit là-bas à des chromosomes aléatoires.

J'utilise codeblocks IDE et le débogueur gdb. La trace de la pile lorsque l'erreur de segmentation se produit a 4 adresses de mémoire et un wsncpy() de fonction.

Était-ce utile?

La solution

void Population::clearPool( std::vector <Chromosome*> & a )
{
   for ( int i = 0; i < a.size(); i++ ) {
      delete a[i];
   }
   a.clear();
}

Notez que le vecteur est passé par référence. Dans votre code, une copie du vecteur est utilisé, ce qui signifie qu'il ne change pas dans le programme appelant. Parce que vous supprimez les pointeurs dans la copie, les pointeurs dans l'original sont maintenant tous les invalides - Je suppose que vous utilisez ces pointeurs non valides d'une manière non représentée dans le code affiché

.

En tant que deux solutions de modèle ont été affichés qui utilisent des algorithmes de la bibliothèque C ++, vous pouvez également envisager une solution de modèle qui ne fonctionne pas:

template <class C> void FreeClear( C & cntr ) {
    for ( typename C::iterator it = cntr.begin(); 
              it != cntr.end(); ++it ) {
        delete * it;
    }
    cntr.clear();
}

En utilisant cela, vous pouvez libérer tout conteneur d'objets alloués dynamiquement:

vector <Chromosome *> vc;
list <Chromosome *> lc;
// populate & use
FreeClear( lc );
FreeClear( vc );

Autres conseils

version modifiée légèrement par rapport à (@ 1800 INFORMATION).

  struct DeleteFromVector
    {
        template <class T>
        void operator() ( T* ptr) const
        {
            delete ptr;
        }
    };


std::for_each(aVec.begin(), aVec.end(), DeleteFromVector());

Je ne sais pas pourquoi vous s'écraser, mais je suppose que il est possible que la taille du vecteur est pas la même que la taille que vous passez. Je remarque aussi que vous itérez de 0 à taille-2 , ne vous veut pas dire aller jusqu'au bout?

Une façon de supprimer tous les éléments du tableau en utilisant idiomatiques C ++ est quelque chose comme ceci:

template<class T>
class deleter
{
  public:
    void operator()(const T* it) const
    {
      delete it;
    }
};

std::for_each(a.begin(), a.end(), deleter<Chromosome>());

Boost lambda a déjà un foncteur pour la suppression de séquences de pointeurs, par la manière:

std::for_each(a.begin(), a.end(), boost::lambda::delete_ptr());

Êtes-vous sûr que chaque pointeur dans les points de vecteur à un autre objet? (À savoir que deux pointeurs ne le font pas tous les deux vers le même objet que vous essayez de supprimer deux fois.

Êtes-vous sûr que vous ne supprimez pas certains des pointeurs avant d'appeler cette méthode? (À savoir êtes-vous sûr que chaque pointeur dans les points de liste à un objet valide?)

La raison la plus probable appelle supprimer deux fois pour la même adresse. Cela peut se produire si vous avez ajouté un objet plus d'une fois au vecteur. Pour détecter cette insérer une déclaration qui sortie l'adresse de l'objet que vous alors supprimer .

printf( "will delete %d\n", (int)c );
delete c;

J'ai trouvé le problème.

Il était dans le plus bien caché (par nul autre que moi vieux stupide) placer pourrait être.

Comme certains auraient pu le deviner est un programme d'algorithmes génétiques. Il est pour un tutoriel que je fais. Je choisissais les points de croisement pour les chromosomes au hasard d'une fonction de roue de roulette que je fait. Eh bien ... à l'intérieur, il y avait un -1 qui ne devrait pas être là. Cela détruit littéralement tout, et éventuellement conduire à une erreur de segmentation.

Merci à tous pour votre aide, j'ai vu des pratiques vraiment bien dans ce poste que je compte suivre

Je recommande d'utiliser un pointeur intelligent (ex: auto_ptr) au lieu de pointeur brut et juste utiliser vecteur :: méthode claire qui appellera la destructor pour chaque élément

void Population::clearPool(std::vector<Chromosome*>& a)
{
    for(size_t i = 0; i < a.size(); i++) {
        delete a[i];
    }

    a.clear();
}

Il semble que certains pointeurs dans votre code ne référencent pas correct objets chromosomiques. Cela peut se produire, si vous essayez de supprimer certains objets deux fois par suite de code:

Population p;
vector<Chromosome*> chromosomes;
p.clearPool(chromosomes,chromosomes.size()); // You pass by value, so chromosomes is not changed
p.clearPool(chromosomes,chromosomes.size()); // Delete already deleted objects second time

Vous trouverez peut-être utile de ptr_vector Boost pointeur Container bibliothèque afin d'éviter des erreurs similaires

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top