Visual Studio C++, error destructor de clase

Iniciado por Namida, 1 Mayo 2010, 12:56 PM

0 Miembros y 3 Visitantes están viendo este tema.

Namida

¡Muy buenas!

Les comento. Desde hace tiempo llevo teniendo problemas al intentar liberar un array dinámico incluido en una clase, a traves de un destructor de clase.

A modo ilustrativo propongo el siguiente ejemplo:
class A{
private:
int** dato;
int Indice_1,Indice_2;
public:
void crear(int X,int Y){
//Se define el tamaño del array dato
Indice_1=X;
Indice_2=Y;
//Se reserva la memoria (Array Dinámico)
dato=new int *[X];
for(int i=0;i<X;i++){
dato[i]=new int [Y];
for(int j=0;j<Y;j++){
dato[i][j]=0;
}
}
}
~A(){
//Se libera la memoria
for(int i=0;i<Indice_1;i++){
delete[] dato[i];
}
delete[] dato;
}
};


El error que genera dice así:
Excepción no controlada en 0x102d31ea (msvcr90d.dll) en PRINCIPAL.exe: 0xC0000005: Infracción de acceso al leer la ubicación 0xfeeefee2.

Lo curioso del caso es que empleando el prefijo del destructor de clase ~ se produce el error pero, renombrando el algoritmo como una función void, esto no ocurre y funciona correctamente (se libera la memoria correctamente y el programa actua sin anomalías).

void borrarA(){
       //Se libera la memoria
       for(int i=0;i<Indice_1;i++){
delete[] dato[i];
}
delete[] dato;
}


Empleando el primer código, pero situando un testigo en el destructor (tipo cout<<"DESTRUCTOR INVOCADO"<<endl), resulta que éste es invocado dos veces.  Una, cuando yo lo llamo, y otra, cuando el programa intenta finalizar. Siendo esta segunda vez la que causa el error.

Por lo que mis preguntas son:
¿Por qué el destructor es invocado una segunda vez cuando la hinstancia de la clase ya se ha 'destruido'?
¿Por qué funciona correctamente bien con void y no asi con ~ (propio del destructor de clase)?

Menciono que empleo como compliador el Visual Studio C++ 2008... creo que los tiros van por aqui jeje

¡¡Gracias por la ayuda!!

Lambda

El problema es que NO debes de llamar tu al destructor, de eso ya se encarga el compilador.

Namida

Cita de: Lambda en  1 Mayo 2010, 14:33 PM
El problema es que NO debes de llamar tu al destructor, de eso ya se encarga el compilador.

Si no llamo al destructor la memoria no es liberada hasta el final del programa. Cosa que no deseo...

Por Default, el compilador aporta un destructor, pero si lo empleo no me libera la memoria (lo he comprobado)... asi que estamos en las mismas. Tengo que definir un método que libere la memoria...

En la práctica, lo mismo me da definir un funcion void que el destructor propiamente dicho... pero este error que comento, a priori, no debería ocurrir...

Si alguien sabe algo¿?

.:BlackCoder:.

#3
Libera Y y despues X...  a ver q tal... Saludos

EDIT: Olvida este comentario xD es que me acabo de parar y nu vi bien... jeje
"No te esfuerzes por saber mas, esfuerzate por ser el mejor en lo que sabes... Y asi sabras mas" .:BlackCoder:. jajaja




Namida

Es de sabios rectificar xDD...

Lambda me he dado cuenta que tienes razón. No tengo porque llamar al destructor, el error es ese... GRACIAS!! ;-)

Entonces, entiendo que se libera la memoria dinámica tras salir del ámbito?? y que no es necesario definir un método que la libere??

.:BlackCoder:.

No, omo tu mismo dijiste el destrutor se llama al salir del ambito... A menos que la instancia sea un puntero... Y sin embargo el compilador libera ese espacio... Pero se recomienda que uno mismo libere la memoria... Saludos
"No te esfuerzes por saber mas, esfuerzate por ser el mejor en lo que sabes... Y asi sabras mas" .:BlackCoder:. jajaja




Namida

#6
De hecho, eso mismo he leido... Se recomienda que se libere. De todas formas, no me fio de mis fuentes y al parecer Lambda tiene razón sobre el comportamiento del compilador... Si actúa así por default ó simplemente es como debe ser, para solucionar mi problema y liberar la memoria asignada dentro del un mismo ámbito simplemente hay que tomar punteros.
Un pseudocodigo
class Objeto{...};

int main(int argc,char*argv[]){
Objeto* puntero;
puntero=new Objeto; /*se reserva la memoria*/
/*Operaciones con el objeto*/{...};
delete puntero; /*se libera la memoria*/
return 0;
}


Considero pues, solucionado el tema  ;-)

PD:Releyendo mis fuentes, no sé cómo puede presentarse en un libro de este tipo (programación) frases ambigüas que llevan a confuciones...

Namida

Cita de: El_nuevo_HH en  1 Mayo 2010, 16:05 PM
Libera Y y despues X...  a ver q tal... Saludos

EDIT: Olvida este comentario xD es que me acabo de parar y nu vi bien... jeje

Imagino xDD... no veía nada que liberar xDDD... enga, saludos ;)

Eternal Idol

Te falto el codigo del programa ... asi podemos saber EXACTAMENTE que estas haciendo. La logica es muy simple, si usas new usas delete, sino no.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón