Discussion:
problema al liberar memoria con free(...)
(demasiado antiguo para responder)
Marcos Medina
2006-04-25 14:05:20 UTC
Permalink
Hola amigos, el problema que me da al ejecutar el programilla es el
siguiente:

*** glibc detected *** free(): invalid next size (fast): 0x080f0018 ***

¿Alguien sabe a que se refiere?

Utilizo unas estructuras con punteros y la función que libera memoría
es recursiva:
void libero_pic_vall(PIC_VALL pico)
{
LISTA lista,aux;
if (pico->sucesores == NULL)
{
printf("liberamos nodo hoja\n");
free(pico);
return;
}
lista=pico->sucesores;
while (lista != NULL)
{
libero_pic_vall(lista->hijo);
aux=lista;
lista=lista->sig;
printf("liberamos un elemento lista\n");
free(aux);
}
printf("liberamos nodo intermedio\n");
free(pico);
return;
}

Cuando pongo, free(&pico) no da esté error, da otro violación de memoría
pero lo da más tarde, o sea que la función recursiva avanza mucho más. Con
el otro error lo da nada más llegar al nodo hoja, o sea al primer free().

La definición de las estructuras son:
typedef struct pic_vall * PIC_VALL;
typedef struct lista * LISTA;

struct lista
{
PIC_VALL hijo;
LISTA sig; /* lista de sucesores */
};

struct pic_vall
{
char letra; // letra del nodo
int num_suc; // numero de sucesores
PIC_VALL padre; // Enlaces al padre en la estructura
LISTA sucesores; // Lista a los sucesores
};

Muchas gracias de antemano.....

Y comprenderé que no me contesteís con todo lo que he escritoooo, pero bueno
no le veo solución y a ver si alguien se animaaaa....
--
Atentamente Marcos Medina


"Saber que se sabe lo que se sabe y que no se sabe lo que no se sabe; he
aquí el verdadero saber."

CONFUCIO
- Filósofo chino
Bartomeu
2006-04-25 15:31:57 UTC
Permalink
El free libera la memoria, pero no pone el puntero a NULL. Por lo tanto no
detectas los punteros ya liberados y estás liberando basura, con lo cual
tarde o temprano petará..

Te recomiendo que cambies todos los free por:
free(pico);
pico =NULL;

O si no te asustan los defines utiliza este:

#define FREE(PTR) {free(PTR); PTR=NULL;}

y a partir de entonces
FREE(pico);
FREE(aux);

De todas maneras recuerda que es un define y no hagas FREE(aux++),

suerte.
Post by Marcos Medina
Hola amigos, el problema que me da al ejecutar el programilla es el
*** glibc detected *** free(): invalid next size (fast): 0x080f0018 ***
¿Alguien sabe a que se refiere?
Utilizo unas estructuras con punteros y la función que libera memoría
void libero_pic_vall(PIC_VALL pico)
{
LISTA lista,aux;
if (pico->sucesores == NULL)
{
printf("liberamos nodo hoja\n");
free(pico);
return;
}
lista=pico->sucesores;
while (lista != NULL)
{
libero_pic_vall(lista->hijo);
aux=lista;
lista=lista->sig;
printf("liberamos un elemento lista\n");
free(aux);
}
printf("liberamos nodo intermedio\n");
free(pico);
return;
}
Cuando pongo, free(&pico) no da esté error, da otro violación de memoría
pero lo da más tarde, o sea que la función recursiva avanza mucho más. Con
el otro error lo da nada más llegar al nodo hoja, o sea al primer free().
typedef struct pic_vall * PIC_VALL;
typedef struct lista * LISTA;
struct lista
{
PIC_VALL hijo;
LISTA sig; /* lista de sucesores */
};
struct pic_vall
{
char letra; // letra del nodo
int num_suc; // numero de sucesores
PIC_VALL padre; // Enlaces al padre en la estructura
LISTA sucesores; // Lista a los sucesores
};
Muchas gracias de antemano.....
Y comprenderé que no me contesteís con todo lo que he escritoooo, pero bueno
no le veo solución y a ver si alguien se animaaaa....
--
Atentamente Marcos Medina
"Saber que se sabe lo que se sabe y que no se sabe lo que no se sabe; he
aquí el verdadero saber."
CONFUCIO
- Filósofo chino
Marcos Medina
2006-04-26 09:35:34 UTC
Permalink
Hola Bartomeu.....

Mira el problema más al grano es esté:

mi problema es con el free(pico) y el error que me da es el siguiente:

*** glibc detected *** free(): invalid next size (fast): 0x0804b008 ***

y lo que hago es lo siguiente:

Defino dos estructuras de la siguiente manera:
typedef struct pic_vall * PIC_VALL;
typedef struct lista * LISTA;

struct lista
{
PIC_VALL hijo;
LISTA sig; /* lista de sucesores */
};

/** Estructura para almacenar una letra.
* numero de sucesores, apuntador al padre
* y lista encadenadas de sucesores
*/
struct pic_vall
{
char letra; // letra del nodo
int num_suc; // numero de sucesores
PIC_VALL padre; // Enlaces al padre en la estructura
LISTA sucesores; // Lista a los sucesores
};

Utilizio está función pa inicializar estructura:

int inicializa_pic_vall(PIC_VALL * pico)
{
//Incializamos estructura pa almacenar las estructuras necesarias...

*pico=malloc(sizeof(PIC_VALL));
(*pico)->letra=(char)NULL;
(*pico)->num_suc=0;
(*pico)->padre=NULL;
(*pico)->sucesores=NULL;

return true;
}

Y luego un sencillo free en el main...:

inicializa_pic_vall(&pico);
pico->letra='a';
printf("letra=%c
\tnum_sun=%d\tpadre=%X\tdir=%X\n",pico->letra,pico->num_suc,pico->padre,pico);
free(pico);

Y obtengo esto por pantalla:
$ ./lema
letra=a num_sun=0 padre=0 dir=804B008
*** glibc detected *** free(): invalid next size (fast): 0x0804b008 ***

¿Alguna idea de porque me falla? ¿Que estoy haciendo mal?

Muchas Gracias de antemano :)
Bartomeu
2006-04-26 11:04:06 UTC
Permalink
Creo que el problema no esta en free(pico), sino en inicializa_pic_vall.
Si free falla es porque no apunta a lo que tu te crees.
Te comento entre líneas, y al final te propongo una alternativa, sigue
leyendo...
Post by Marcos Medina
[...]
typedef struct pic_vall * PIC_VALL;
typedef struct lista * LISTA;
[...]
int inicializa_pic_vall(PIC_VALL * pico)
{
//Incializamos estructura pa almacenar las estructuras
necesarias...
*pico=malloc(sizeof(PIC_VALL));
Aqui creo que tendría que ser sizeof(pic_vall). Sólo estas reservando
memoria para un puntero (PIC_VALL es un puntero, según tu typedef) Te
recomiendo que cambies en el typedef PIC_VALL por P_PIC_VAL o pPIC_VALL,
así no confundirás la estructura por un puntero a la estructura.
Análogamente, cambia LISTA por P_LISTA o pLISTA.

Como medida de seguridad y en la fase de prueba, añade la siguiente
linea:

printf("pico=%X\n",pico);

y comprueba que es la misma dirección que tienes fuera de la función.
Post by Marcos Medina
(*pico)->letra=(char)NULL;
(*pico)->num_suc=0;
(*pico)->padre=NULL;
(*pico)->sucesores=NULL;
return true;
}
[...]
Te propongo esta alternativa. Personalmente nunca me han gustado los
punteros a punteros, siempre llega un momento que no sabes si tienes el
puntero, el puntero al puntero o la cosa apuntada ;-), aunque reconozco que
hay veces que no hay mas remedio que trabajar con ellos.

typedef struct pic_vall * pPIC_VALL;
typedef struct lista * pLISTA;

struct lista
{
pPIC_VALL hijo;
pLISTA sig; /* lista de sucesores */
};

struct pic_vall
{
char letra; // letra del nodo
int num_suc; // numero de sucesores
pPIC_VALL padre; // Enlaces al padre en la
estructura
pLISTA sucesores; // Lista a los sucesores
};


pPIC_VALL inicializa_pic_vall(void)
{
pPIC_VALL pico;
pico=malloc(sizeof(pic_vall));
pico->letra=(char)NULL;
pico->num_suc=0;
pico->padre=NULL;
pico->sucesores=NULL;

return pico;
}

Y luego un sencillo free en el main...:

pPIC_VALL pico;
pico = inicializa_pic_vall();
pico->letra='a';
printf("letra=%c
\tnum_sun=%d\tpadre=%X\tdir=%X\n",pico->letra,pico->num_suc,pico->padre,pico);
free(pico);
pico = NULL;

Te recuerdo lo que te dije en el primer mensaje: después de free pon el
puntero a NULL. Tampoco estaría de más comprobar que el malloc no falla
confirmando que ha reservado la memoria pedida.

Suerte.

Loading...