Frage

Ich habe einen Vektor von Zeigern auf eine Klasse. Ich brauche ihre Destruktoren zu nennen und deren Speicher frei. Da sie Vektor von Zeigern vector.clear sind () gibt die job.So nicht ging ich auf, es zu tun manuell wie folgt:

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;

    }

}

Die printf da drin ist, da ich ein Gespräch destructor um zu sehen haben, was Chromosome die Segmentierungsfehler passiert. Wenn Clear () aufgerufen wird und sagen, dass wir eine Größe von 100 bekamen, kann es einen Segmentierungsfehler in jedem Chromosome zwischen 0 und 100 geben.

Ich habe keine Ahnung, warum dies geschehen könnte noch habe ich einen Weg, um tatsächlich das zu finden, was mit Haltepunkten, da beim Debuggen falsch ist alles was ich sehe ist, dass sie zufällig Chromosomen dort geschehen.

Ich bin mit Codeblöcken IDE und den GDB-Debugger. Der Stack-Trace, wenn die Segmentierungsfehler passiert, hat vier Speicheradressen und eine Funktion wsncpy().

War es hilfreich?

Lösung

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

Beachten Sie, dass der Vektor als Referenz übergeben wird. In Ihrem Code, wird eine Kopie des Vektors verwendet, was bedeutet, dass es im rufenden Programm unverändert ist. Da Sie die Zeiger in der Kopie löschen, sind die Zeiger in dem Original jetzt alles ungültig - Ich vermute, dass Sie diese ungültigen Zeiger in irgendeine Weise verwenden, nicht im Code gezeigt Sie auf dem Laufenden

.

Als ein paar Template-Lösungen geschrieben wurde, die C ++ Bibliothek Algorithmen verwenden, mögen Sie vielleicht auch eine Vorlage Lösung zu berücksichtigen, dass nicht:

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

das Verwenden Sie einen Container von dynamisch zugewiesenen Objekte befreien kann:

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

Andere Tipps

Leichte modifizierte Version im Vergleich zu (@ 1800 INFORMATIONEN).

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


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

Ich weiß nicht, warum du abstürzt, aber ich denke, dass eine Möglichkeit besteht darin, dass die Größe des Vektors nicht die gleiche wie die Größe, die Sie in sind vorbei. Auch ich feststellen, von 0 bis Größe-2 iterieren , meinst du nicht den ganzen Weg bis zum Ende gehen?

Eine Möglichkeit, alle Elemente im Array mit idiomatischen C ++ zu löschen ist so etwas wie folgt aus:

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 hat bereits einen Funktor für Sequenzen von Zeigern, durch die Art und Weise zu löschen:

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

Sind Sie sicher, dass jeder Zeiger in den Vektorpunkten auf ein anderes Objekt? (Das heißt, dass zwei Zeiger nicht beide auf das gleiche Objekt, das Sie versuchen, zweimal zu löschen.

Sind Sie sicher, dass Sie einige der Zeiger nicht löschen, bevor Sie diese Methode aufrufen? (Das heißt sind Sie sicher, dass jeder Zeiger in der Liste auf ein gültiges Objekt?)

Der wahrscheinlichste Grund ruft löschen zweimal für die gleiche Adresse. Dies kann passieren, wenn Sie den Vektor ein Objekt mehr als einmal zugegeben. Um festzustellen, dies einige Anweisung einfügen, die die Adresse des Objekts ausgegeben werden Sie dann löschen .

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

Ich fand das Problem.

Es war in den meisten gut versteckt (von keinem geringeren als dumm alt me) legen es sein könnte.

Wie einige haben vielleicht erraten dies eine genetische Algorithmen Programm. Es ist für ein Tutorial ich machen werde. Ich war die Wahl der Kreuzungspunkte für die Chromosomen zufällig von einer Roulette-Rad-Funktion, die ich gemacht. Nun ... innen dort gab es eine -1, die nicht da sein sollte. Das zerstörte buchstäblich alles, und schließlich zu einem Segmentierungsfehler führen.

Vielen Dank für Ihre Hilfe, sah ich einige wirklich gute Praktiken in diesem Beitrag, die ich zu folgen beabsichtigen

Ich empfehle Smart-Pointer zu verwenden (zB: auto_ptr) statt Rohzeiger und nur Vektor verwenden :: klare Methode, die das destructor für jedes Element rufen

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

    a.clear();
}

Es scheint, dass einige Hinweise in Ihrem Code nicht korrekt Chromosome Objekte verweisen können. Dies kann passieren, wenn Sie versuchen, einige Objekte zweimal als Folge des Code zu löschen:

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

Sie können nützlichen ptr_vector finden von Boost-Pointer Container Bibliothek , um ähnliche Fehler zu vermeiden

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top