Duda c++, hacer un destructor

varuk

Buenas.

Tengo la siguiente estructura:

struct Usuario {

string nombre;
int numeroID;
list<miTipo *> listaMensajes;

};

class AlmacenaUsuarios {

  private:
	list<Usuario> * arrayNombres[1000];
	list<Usuario>::iterator it;
	

	

  public:
	 AlmacenaUsuarios();
	~ AlmacenaUsuarios() {

		for (int i = 0; i<1000; i++){
			arrayNombres[i]->clear();
		}

	 }

Vale, ya lo he solucionado. Tenía el destructor de AlmacenaUsuario() mal.

Lo tenía como

~ AlmacenaUsuarios() {

		for (int i = 0; i<1000; i++){
			delete arrayNombres[i];
		}

No sé en que estaba pensando... ha sido poner clear() y solucionarse

elkaoD

Los destructores se llaman cuando se hace el respectivo delete tras el new o en efecto, de forma automática para objetos ligados a otros (todo lo que no se haya creado con new) cuando se hace el delete del objeto contenedor.

De todas formas, ¿seguro que quieres tener un iterador como atributo? Lo normal es que tengas un método getIterator() que devuelva el iterador cada vez que lo quieras usar. Los iteradores son de un sólo uso y cuando terminas de hacer lo que sea debes descartarlos. Además, puedes tener problemas si la lista cambia pero no haces un nuevo get del iterador. No sé cuál sería exactamente el comporamiento, pero una de dos: o se te corrompe el iterador, o acabas iterando sólo sobre los elementos existentes en la creación del iterador. Tal y como lo tienes, vaticino punteros nulos everywhere.

Tampoco entiendo muy bien eso de arrayNombres[x]->clear(); ¿Qué es lo que quieres hacer exactamente? Si quieres borrar sólo el contenedor, tienes que hacer delete arrayNombres pero no puedes porque es estático así que se encarga ello sólo cuando destruyes AlmacenaUsuarios. Si lo que quieres es borrar los elementos asociados, tienes que hacer delete arrayNombres[x] para cada elemento x.

El clear se hace sólo sobre arrayNombres. No tiene sentido arrayNombres[x]->clear() sino como mucho arrayNombres->clear(), sobre la lista, no sobre los elementos. Aún así sigue sin tener mucho sentido hacer clear() a la lista cuando la vas a borrar inmediatamente. ¿Para qué quieres vaciar una lista que vas a destruir posteriormente? Destruyes la lista y por tanto da igual que esté vacía o llena, la lista se va a pastar.

Si los objetos para nombres no los tienes referenciados por ningún otro lado, hacer clear() a la lista pero no borrar los elementos es un memory leak como una casa. La memoria asignada a cada uno de los elementos no se destruye en ningún momento, y como has borrado la referencia, no tienes ninguna forma de referenciarlos y por tanto de liberar la memoria, así que se quedan colgando en el limbo del heap de tu programa.

1 2 respuestas
BLZKZ

+1 a #2 , #1 ten en cuenta que esto es OO, que consiste en "delegar trabajo". Cuando haces un delete de un objeto, este llama a los destructores que tiene por debajo, haciendo el ->clear no entiendo lo que estas haciendo xD, se tiene que hacer delete arrayNombres como te dice elkaod, sin for ni leches.

varuk

Cierto, muchas gracias a ambos ^. Voy a tomarme un descansando, que ya no carburo bien creo.

#2 mmm sin el for y lo probé y no entiendo que pase esto al ejecutar... sin el for borra el array pero no los elementos que contiene el array. Eso tenía entendido. Además, que al hacer el delete del array directamente luego ejecuto y sale esto:

======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x6b961)[0xb75c3961]
/lib/i386-linux-gnu/libc.so.6(+0x6d28b)[0xb75c528b]
/lib/i386-linux-gnu/libc.so.6(cfree+0x6d)[0xb75c841d]
/usr/lib/i386-linux-gnu/libstdc++.so.6(ZdlPv+0x21)[0xb77a64d1]
/usr/lib/i386-linux-gnu/libstdc++.so.6(
ZdaPv+0x1d)[0xb77a652d]
./a.out[0x8049496]
./a.out[0x804926c]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0xb756ee37]
./a.out[0x8048f21]
======= Memory map: ========
08048000-08052000 r-xp 00000000 08:07 923025

08052000-08053000 r--p 00009000 08:07 923025

08053000-08054000 rw-p 0000a000 08:07 923025

09ecb000-0cdd8000 rw-p 00000000 00:00 0 [heap]
b7400000-b7421000 rw-p 00000000 00:00 0
b7421000-b7500000 ---p 00000000 00:00 0
b7556000-b7558000 rw-p 00000000 00:00 0
b7558000-b76b2000 r-xp 00000000 08:07 654914 /lib/i386-linux-gnu/libc-2.13.so
b76b2000-b76b3000 ---p 0015a000 08:07 654914 /lib/i386-linux-gnu/libc-2.13.

2 respuestas
elkaoD

#4 reléeme bien que te has dejado cosas en el tintero. Tienes que realizar VARIOS pasos.

Primero tienes que eliminar los elementos del array (for blabla... delete array[x]) y luego el contenedor (un simple delete array)

Creo que no tienes muy claro como funciona el sistema de memoria dinámica en C++ así que dale duro al estudio :)

1 respuesta
tirano

#4 Al liberar memoria es posible que se sigan quedando los datos, lo que ocurre es que si alguna variable o metodo necesita memoria podra coger la memoria de dicho array ya que esta libre

BLZKZ

#5 su confusión viene por mi culpa xDDDDDD no me fijé que hizo un array de listas (tampoco entiendo muy bien la razon de hacer eso, lo estás usando como tablas? por que no usas un tad de tablas directamente? xD)

#8 ya ya, por eso preguntaba :)

2 respuestas
varuk

#7 Tenía que hacer una tabla de dispersión abierta. Es decir, por cada posición del array una lista y cuando un elemento, según la función de dispersión, tuviera un valor pues introducirlo en la lista de esa posición del array.

Gracias a todos, por cierto ^^

1 respuesta
elkaoD

#7 ahivá, pues en efecto yo tampoco me había fijado en que era un array de listas! xD Sipe, en efecto, entonces tienes que hacer el delete dentro del for (aunque no debes olvidar borrar también los elementos de las listas previamente.)

1 respuesta
BLZKZ

#9 imagino que los elementos de las listas tendrán sus destructores propios xD

1 respuesta
elkaoD

#10 la lista no contiene sólo un puntero a los objetos, y por tanto hay que hacer el delete a mano?

1 respuesta
varuk

Pues todo aclarado. Os amo.

BLZKZ

#11 al menos yo las listas dinámicas que he hecho/manejado tenían un destructor que llamaba a un método auxiliar que destruía los elementos 1 a 1 xD

Si tienes todos los destructores bien hechos solo te queda delegar, cuando haces el delete de un objeto se hacen llamadas a los destructores por debajo (si fuera necesario) de manera automática, si todo está bien implementado no habrá leaks de memoria.

2 respuestas
varuk

#13 Por esas cosas alguien inventó Java. Aunque C, en este caso C++, es C++. Claro.

1 respuesta
BLZKZ

#14 por eso java maneja como el culo la memoria xDDDDD (java y c#), c++ puede ser un caos de punteros pero si te lo montas bien al menos tendras una optimizacion genial XD

eisenfaust

Java tuvo éxito por el marketing pero también porque hacía y sigue haciendo mucha falta algo mejor que C++. Nadie quiere seguir usando esa patata desarrollada por un amateur en la materia y es una muy buena noticia que esté perdiendo popularidad.

Creo que no existe ningún otro lenguaje en el mundo que haya generado tantas pérdidas. Por desgracia es lo que toca usar en muchísimas ocasiones.

Y sí, sólo entro en este subforo para echar pestes de C++.

2 respuestas
BLZKZ

#16 C fue desarrollada por un amateur en la materia y aun así ha generado muchísimo dinero.

LOc0

Salu2 ;)

elkaoD

#13 hmm, 100% cierto, tengo C++ algo oxidado por lo que veo...

#16 no fue diseñado por aficionados precisamente... además, como dije en nosequé post sobre C (y aplicable a C++), era otra época y el lenguaje es pa' lo que es.

Usuarios habituales

  • elkaoD
  • LOc0
  • BLZKZ
  • eisenfaust
  • varuk
  • tirano