Domanda

Ho un vettore di puntatori a una classe. Ho bisogno di chiamare i loro distruttori e liberare la loro memoria. Dal momento che sono vettore di puntatori vector.clear () non fa il job.So ho continuato a farlo manualmente in questo modo:

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;

    }

}

Il printf in là è dal momento che ho un distruttore di parlare per vedere in che Cromosoma la segmentation fault accade. Quando ClearPool () viene chiamato e dire che abbiamo ottenuto una dimensione di 100, può dare un errore di segmentazione in ogni cromosoma tra 0 e 100.

Non ho idea del perché questo potrebbe accadere né ho un modo per trovare in realtà ciò che c'è di sbagliato in quanto durante il debug con punti di interruzione tutto quello che vedo è che succede lì dentro a cromosomi casuali.

Sto usando codeblocks IDE e il debugger gdb. L'analisi dello stack quando l'errore di segmentazione accade ha 4 indirizzi di memoria e una funzione wsncpy().

È stato utile?

Soluzione

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

Si noti che il vettore viene passato per riferimento. Nel codice, una copia del vettore viene utilizzato, il che significa che è invariato nel programma chiamante. Perché si eliminano i puntatori nella copia, i puntatori in originale sono ora tutti validi - ho il sospetto che si sta utilizzando i puntatori non validi in qualche modo non mostrato nel codice che avete inviato

.

Come un paio di soluzioni template sono stati pubblicati che utilizzano algoritmi della libreria C ++, si potrebbe anche prendere in considerazione una soluzione modello che non:

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

Con questo è possibile liberare qualsiasi contenitore di oggetti allocati dinamicamente:

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

Altri suggerimenti

Lieve versione modificata rispetto a (@ 1800 INFORMAZIONI).

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


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

Non so perché si sta schiantarsi, ma credo che una possibilità è che la dimensione del vettore non è la stessa come la dimensione che sta passando. Inoltre ho notato che si sta iterazione da 0 a size-2 , non ve ne intendi andare fino in fondo fino alla fine?

Un modo per eliminare tutti gli elementi di un array tramite idiomatica C ++ è qualcosa di simile:

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 ha già un funtore per l'eliminazione di sequenze di puntatori, tra l'altro:

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

Sei sicuro che ogni puntatore nei punti vettoriali a un oggetto diverso? (Vale a dire che due puntatori non lo fanno sia punto allo stesso oggetto, che si sta cercando di eliminare il doppio.

Sei sicuro che non si eliminano alcuni dei puntatori prima di chiamare questo metodo? (Vale a dire sei sicuro che ogni puntatore nei punti elenco a un oggetto valido?)

La ragione più probabile è chiamata eliminare due volte per lo stesso indirizzo. Questo può accadere se è stato aggiunto un oggetto più di una volta al vettore. Per rilevare questo inserire qualche dichiarazione che sarà in uscita l'indirizzo dell'oggetto sarà quindi eliminare .

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

Ho trovato il problema.

E 'stato nel più ben nascosta (da niente meno che stupido vecchio me) posto che potrebbe essere.

Per quanto alcuni potrebbero aver intuito questo è un programma algoritmi genetici. E 'per un tutorial che sto facendo. Stavo scegliendo i punti di incrocio per i cromosomi casualmente da una funzione roulette che feci. Beh ... là dentro, c'era un -1 che non dovrebbe essere lì. Che ha distrutto letteralmente tutto, e alla fine portano a un errore di segmentazione.

Grazie a tutti per il vostro aiuto, ho visto alcune veramente buone pratiche in questo post, che ho intenzione di seguire

Consiglio di usare puntatore intelligente (es: auto_ptr) invece di puntatore non elaborato e basta usare vector :: metodo chiaro che chiamerà il distruttore per ciascun elemento

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

    a.clear();
}

Sembra che alcune indicazioni nel codice non fanno riferimento gli oggetti Cromosoma corretti. Questo può accadere, se si tenta di eliminare alcuni oggetti due volte a seguito di codice:

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

Si possono trovare utile ptr_vector da Boost Pointer Container biblioteca al fine di evitare errori simili

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top