sirven - C++ std:: vector de borrado de punteros y fallas de segmentación
punteros y vectores en c (10)
¿Estás seguro de que cada puntero en el vector apunta a un objeto diferente? (es decir, que dos punteros no apuntan al mismo objeto, que intenta eliminar dos veces).
¿Estás seguro de que no eliminas algunos de los indicadores antes de llamar a este método? (es decir, ¿está seguro de que cada puntero de la lista apunta a un objeto válido?)
Tengo un vector de punteros a una clase. Necesito llamar a sus destructores y liberar su memoria. Dado que son vectores de punteros, vector.clear () no hace el trabajo. Por lo tanto, procedí a hacerlo manualmente así:
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;
}
}
El printf allí es porque tengo un destructor que habla para ver en qué cromosoma ocurre la falla de segmentación. Cuando se llama a clearPool () y decimos que tenemos un tamaño de 100, puede dar un error de segmentación en cualquier cromosoma entre 0 y 100.
No tengo idea de por qué esto podría estar sucediendo ni tengo una manera de encontrar realmente lo que está mal, ya que mientras estoy depurando con puntos de interrupción, todo lo que veo es que sucede allí al azar en los cromosomas.
Estoy usando codeblocks IDE y el depurador gdb. El seguimiento de la pila cuando ocurre la falla de segmentación tiene 4 direcciones de memoria y una función wsncpy()
.
Booster lambda ya tiene un funtor para eliminar secuencias de punteros, por cierto:
std::for_each(a.begin(), a.end(), boost::lambda::delete_ptr());
Encontré el problema.
Fue en el lugar más oculto (por nada menos que estúpido) que podría ser.
Como algunos podrían haber adivinado, este es un programa de algoritmos genéticos. Es para un tutorial que estoy haciendo. Estaba eligiendo los puntos de cruce para los cromosomas al azar de una función de rueda de la ruleta que hice. Bueno ... por dentro, había un -1 que no debería estar allí. Eso destruyó literalmente todo, y finalmente condujo a una falla de segmentación.
Gracias a todos por su ayuda, vi algunas prácticas realmente buenas en esta publicación que pretendo seguir
La razón más probable es llamar a eliminar dos veces para la misma dirección. Esto puede suceder si agregaste un objeto más de una vez al vector. Para detectar esto, inserte una declaración que mostrará la dirección del objeto que luego eliminará .
printf( "will delete %d/n", (int)c );
delete c;
Ligera versión modificada en comparación con (@ 1800 INFORMACIÓN).
struct DeleteFromVector
{
template <class T>
void operator() ( T* ptr) const
{
delete ptr;
}
};
std::for_each(aVec.begin(), aVec.end(), DeleteFromVector());
No sé por qué estás chocando, pero supongo que una posibilidad es que el tamaño del vector no sea el mismo que el tamaño que estás pasando. También noto que estás iterando de 0 a tamaño 2, ¿verdad? no significa ir todo el camino hasta el final?
Una forma de eliminar todos los elementos de la matriz utilizando C ++ idiomático es algo como esto:
template<class T>
class deleter
{
public:
void operator()(const T* it) const
{
delete it;
}
};
std::for_each(a.begin(), a.end(), deleter<Chromosome>());
Parece que algunos punteros en su código no hacen referencia a los objetos cromosómicos correctos. Esto puede suceder, si intenta eliminar algunos objetos dos veces como resultado del código:
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
Puede encontrar ptr_vector útil de Boost Pointer Container Library para evitar errores similares
Recomiendo usar el puntero inteligente (es decir: auto_ptr) en lugar del puntero sin formato y simplemente usar el método vector :: clear que llamará al destructor para cada elemento
void Population::clearPool( std::vector <Chromosome*> & a )
{
for ( int i = 0; i < a.size(); i++ ) {
delete a[i];
}
a.clear();
}
Tenga en cuenta que el vector se pasa por referencia. En su código, se utiliza una copia del vector, lo que significa que no se modifica en el programa de llamada. Debido a que elimina los punteros en la copia, los punteros en el original ahora no son válidos. Sospecho que está usando esos punteros no válidos de alguna forma que no se muestra en el código que publicó.
Como se han publicado un par de soluciones de plantilla que usan algoritmos de biblioteca de C ++, es posible que también desee considerar una solución de plantilla que no:
template <class C> void FreeClear( C & cntr ) {
for ( typename C::iterator it = cntr.begin();
it != cntr.end(); ++it ) {
delete * it;
}
cntr.clear();
}
Al usar esto, puede liberar cualquier contenedor de objetos asignados dinámicamente:
vector <Chromosome *> vc;
list <Chromosome *> lc;
// populate & use
FreeClear( lc );
FreeClear( vc );
void Population::clearPool(std::vector<Chromosome*>& a)
{
for(size_t i = 0; i < a.size(); i++) {
delete a[i];
}
a.clear();
}