Foros del Web » Programación para mayores de 30 ;) » Programación General »

Problemas con la funcion Free del c

Estas en el tema de Problemas con la funcion Free del c en el foro de Programación General en Foros del Web. Hola a todos, Esta es mi primera intervencion en este foro. Tengo un programa que no me da ningun problema si no libero ningun vector. ...
  #1 (permalink)  
Antiguo 26/04/2005, 02:11
 
Fecha de Ingreso: abril-2005
Mensajes: 6
Antigüedad: 19 años
Puntos: 0
Información Problemas con la funcion Free del c

Hola a todos,

Esta es mi primera intervencion en este foro.

Tengo un programa que no me da ningun problema si no libero ningun vector.

El problema me llega al utilizar la funcion free. Se ejecuta correctamente hasta que llega al free.

El error que suele aparecer es:

Debug Assertion Failed!
Program ....
File: dbgheap.c
Line: 1011

Expression: _CrtIsValidHeapPointer (pUserData)

For information on how your program can cause an assertion failure, see the Visual C++
documentation on asserts.


Alguien sabe a que es debido??

Gracias por adelantado,

Oriol
  #2 (permalink)  
Antiguo 26/04/2005, 03:41
Avatar de Eternal Idol  
Fecha de Ingreso: mayo-2004
Ubicación: Lucentum
Mensajes: 6.192
Antigüedad: 20 años
Puntos: 74
¿El vector es de la STL?
¿Estas reservando la memoria en una CRT y liberandola en otra?
__________________
¡Peron cumple, Evita dignifica! VIVA PERON CARAJO
  #3 (permalink)  
Antiguo 26/04/2005, 03:49
 
Fecha de Ingreso: abril-2005
Mensajes: 6
Antigüedad: 19 años
Puntos: 0
Hola

Perdona mi ignorancia,

QUe es una STL? Y un CRT??

Yo hago una reserva memoria con el malloc para un vector de enteros.

ejemplo:

v=(int *)malloc(n*sizeof(int));


y luego, cuando ya no lo necesito mas doy la instruccion free(v); y me da el error antes mencionado.

Gracias,

Oriol
  #4 (permalink)  
Antiguo 26/04/2005, 04:38
Avatar de Eternal Idol  
Fecha de Ingreso: mayo-2004
Ubicación: Lucentum
Mensajes: 6.192
Antigüedad: 20 años
Puntos: 74
Olvida la STL porque estas usando un array y no una clase vector.

La CRT es la C Runtime Library, en este caso no deberia haber ningun problema. ¿Estas mezclando DLLs? Osea, estas reservando en una DLL y liberando en tu programa o viceversa.

Sino pone el codigo porque deberia funcionar.
__________________
¡Peron cumple, Evita dignifica! VIVA PERON CARAJO
  #5 (permalink)  
Antiguo 26/04/2005, 04:53
 
Fecha de Ingreso: abril-2005
Mensajes: 6
Antigüedad: 19 años
Puntos: 0
Diria que no

Has escrito:

Estas reservando en una DLL y liberando en tu programa o viceversa.

Diria que no?? Como puedo saber eso?

Lamento tanta ignorancia pero es que soy relativamente nuevo en esto!!

Gracias de nuevo
  #6 (permalink)  
Antiguo 26/04/2005, 05:10
Avatar de Eternal Idol  
Fecha de Ingreso: mayo-2004
Ubicación: Lucentum
Mensajes: 6.192
Antigüedad: 20 años
Puntos: 74
Pone el codigo para que podamos ver exactamente que hace.
__________________
¡Peron cumple, Evita dignifica! VIVA PERON CARAJO
  #7 (permalink)  
Antiguo 26/04/2005, 05:40
 
Fecha de Ingreso: abril-2005
Mensajes: 6
Antigüedad: 19 años
Puntos: 0
Mensaje

Este es el codigo,

He resumido el codigo ya que el server no me permite poner todo el codigo. La variable a seguir puede ser por ejemplo *pi. En ninguna de las lineas omitidas se libera este vector.

Al final pongo la libreria la funcion nrutil.c (RESERVA DE MEMORIA)

Mas abajo indico la linea que me da problemas


#include "nrutil.h"

ichar *point_grup;
char **nombre_puntos,**files_arestes,**files_punts,**pu nt_inicial,**punt_final;


int *punts_elimin,*pi,*pf,*flag_aresta,*grup_aresta;
int **punts,**arestes_in;

double *gamm,*obs,*topo;




int main (int argc,char **argv)

{



if (argc == 1)
{
printf ("Usage: %s filename\n", argv[0]);
exit (1);
}
strcpy (filename, argv[1]);


if (!(in1 = fopen (filename, "r"))) nrerror (strcat (strcat ("Cannot open ", filename), " file"));



printf("INPUT DATA\n");

input_data(); //read and allocate the input parameters data


************************************************** ********
ESTA ES LA INSTRUCCION QUE ME DA PROBLEMAS

-----> free_ivector(pi,1,numero_de_observaciones);
************************************************** ******
free_dvector(obs,1,numero_de_observaciones);
free_dvector(gamm,1,numero_de_observaciones);
free_dvector(topo,1,numero_de_observaciones);
fclose (in1);
fclose (in2);
return 0;
}
int input_data()
{
int i,r,k;
int *noss_loc,*nompunt_loc;


fscanf(in1,"%u",&ncol);
fscanf(in1,"%u",&nlin);
fscanf(in1,"%u",&num_prov);
fscanf(in1,"%u",&llindar_incidencia);
fscanf(in1,"%f",&llindar_gamma);


files_arestes=malloc((num_prov+1)*sizeof(char*));

for (i=0;i<num_prov+1;i++)
files_arestes[i]=malloc(10*sizeof(char));

noss_loc=ivector(1,num_prov);
nompunt_loc=ivector(1,num_prov);

noss=0;
for (k=0;k<num_prov;k++)
{

fscanf(in1,"%s",&titolo);
sprintf(files_arestes[k],"%s",titolo);
if((in2=fopen(files_arestes[k],"r"))==NULL)
{

printf("El fitxer d'arestes %s no existeix\n",files_arestes[k]);
getch();
exit(1);

}

i=0;
i1=0;

while ( !feof(in2) )
{
fscanf(in2,"%s",&titolo);
fscanf(in2,"%s",&titolo);
fscanf (in2,"%u",&i1);
fscanf(in2,"%u", &i2);
fscanf(in2,"%f",&f1);
fscanf(in2,"%f",&f1);
fscanf(in2,"%f",&f2);
i++;
}
noss_loc[k+1]=i-1;
noss=noss+i-1;

fclose (in2);
}

numero_de_observaciones=noss;

punt_inicial=malloc(numero_de_observaciones*sizeof (char *));
punt_final=malloc(numero_de_observaciones*sizeof(c har *));

auxarestes=noss;
***************************RESERVO**************** ***************pi = ivector(1,numero_de_observaciones);

********************************************
for(i=0;i<noss;i++)
{
punt_inicial[i]=malloc(10*sizeof(char ));
punt_final[i]=malloc(10*sizeof(char));
flag_aresta[i]=0;
pi[i]=-100;
pf[i]=-100;
grup_aresta[i]=-100;
}
return(1);

}
***************nrutil.c

float *vector();
float **matrix();
float **convert_matrix();
double *dvector();
double **dmatrix();
int *ivector();
int **imatrix();
long int *livector();
float **submatrix();
void free_vector();
void free_dvector();
void free_ivector();
void free_livector();
void free_matrix();
void free_dmatrix();
void free_imatrix();
void free_submatrix();
void free_convert_matrix();
void nrerror();

#include <malloc.h>
#include <stdio.h>

void nrerror(error_text)
char error_text[];
{
void exit();

fprintf(stderr,"Error...\n");
fprintf(stderr,"%s\n",error_text);
fprintf(stderr,"...now exiting to system...\n");
exit(1);
}



float *vector(nl,nh)
int nl,nh;
{
float *v;

v=(float *)malloc((unsigned) (nh-nl+1)*sizeof(float));
if (!v) nrerror("allocation failure in vector()");
return v-nl;
}

int *ivector(nl,nh)
int nl,nh;
{
int *v;

v=( int *)malloc((unsigned) (nh-nl+1)*sizeof( int));
if (!v) nrerror("allocation failure in ivector()");
return v-nl;
}
long int *livector(nl,nh)
long int nl,nh;
{
long int *v;

v=(long int *)malloc((unsigned) (nh-nl+1)*sizeof(long int));
if (!v) nrerror("allocation failure in ivector()");
return v-nl;
}


double *dvector(nl,nh)
int nl,nh;
{
double *v;

v=(double *)malloc((unsigned) (nh-nl+1)*sizeof(double));
if (!v) nrerror("allocation failure in dvector()");
return v-nl;
}



float **matrix(nrl,nrh,ncl,nch)
int nrl,nrh,ncl,nch;
{
int i;
float **m;

m=(float **) malloc((unsigned) (nrh-nrl+1)*sizeof(float*));
if (!m) nrerror("allocation failure 1 in matrix()");
m -= nrl;

for(i=nrl;i<=nrh;i++) {
m[i]=(float *) malloc((unsigned) (nch-ncl+1)*sizeof(float));
if (!m[i]) nrerror("allocation failure 2 in matrix()");
m[i] -= ncl;
}
return m;
}

double **dmatrix(nrl,nrh,ncl,nch)
int nrl,nrh,ncl,nch;
{
int i;
double **m;

m=(double **) malloc((unsigned) (nrh-nrl+1)*sizeof(double*));
if (!m) nrerror("allocation failure 1 in dmatrix()");
m -= nrl;

for(i=nrl;i<=nrh;i++) {
m[i]=(double *) malloc((unsigned) (nch-ncl+1)*sizeof(double));
if (!m[i]) nrerror("allocation failure 2 in dmatrix()");
m[i] -= ncl;
}
return m;
}

int **imatrix(nrl,nrh,ncl,nch)
int nrl,nrh,ncl,nch;
{
int i,**m;

m=( int **)malloc((unsigned) (nrh-nrl+1)*sizeof( int*));
if (!m) nrerror("allocation failure 1 in imatrix()");
m -= nrl;

for(i=nrl;i<=nrh;i++) {
m[i]=( int *)malloc((unsigned) (nch-ncl+1)*sizeof( int));
if (!m[i]) nrerror("allocation failure 2 in imatrix()");
m[i] -= ncl;
}
return m;
}



float **submatrix(a,oldrl,oldrh,oldcl,oldch,newrl,newcl)
float **a;
int oldrl,oldrh,oldcl,oldch,newrl,newcl;
{
int i,j;
float **m;

m=(float **) malloc((unsigned) (oldrh-oldrl+1)*sizeof(float*));
if (!m) nrerror("allocation failure in submatrix()");
m -= newrl;

for(i=oldrl,j=newrl;i<=oldrh;i++,j++) m[j]=a[i]+oldcl-newcl;

return m;
}



void free_vector(v,nl,nh)
float *v;
int nl,nh;
{
free((char*) (v+nl));
}

void free_ivector(v,nl,nh)
int *v,nl,nh;
{
free((char*) (v+nl));
}
void free_livector(v,nl,nh)
long int *v,nl,nh;
{
free((char*) (v+nl));
}

void free_dvector(v,nl,nh)
double *v;
int nl,nh;
{
free((char*) (v+nl));
}



void free_matrix(m,nrl,nrh,ncl,nch)
float **m;
int nrl,nrh,ncl,nch;
{
int i;

for(i=nrh;i>=nrl;i--) free((char*) (m[i]+ncl));
free((char*) (m+nrl));
}

void free_dmatrix(m,nrl,nrh,ncl,nch)
double **m;
int nrl,nrh,ncl,nch;
{
int i;

for(i=nrh;i>=nrl;i--) free((char*) (m[i]+ncl));
free((char*) (m+nrl));
}

void free_imatrix(m,nrl,nrh,ncl,nch)
int **m;
int nrl,nrh,ncl,nch;
{
int i;

for(i=nrh;i>=nrl;i--) free((char*) (m[i]+ncl));
free((char*) (m+nrl));
}



void free_submatrix(b,nrl,nrh,ncl,nch)
float **b;
int nrl,nrh,ncl,nch;
{
free((char*) (b+nrl));
}



float **convert_matrix(a,nrl,nrh,ncl,nch)
float *a;
int nrl,nrh,ncl,nch;
{
int i,j,nrow,ncol;
float **m;

nrow=nrh-nrl+1;
ncol=nch-ncl+1;
m = (float **) malloc((unsigned) (nrow)*sizeof(float*));
if (!m) nrerror("allocation failure in convert_matrix()");
m -= nrl;
for(i=0,j=nrl;i<=nrow-1;i++,j++) m[j]=a+ncol*i-ncl;
return m;
}



void free_convert_matrix(b,nrl,nrh,ncl,nch)
float **b;
int nrl,nrh,ncl,nch;
{
free((char*) (b+nrl));
}
  #8 (permalink)  
Antiguo 26/04/2005, 05:57
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
Joder... Te estamos pidiendo el código que hace relación al array (NO lo llames vector), no todo el código... Y menos si no metes tabuladores y demás (usa la a etiqueta CODE para hacerlo).
  #9 (permalink)  
Antiguo 26/04/2005, 06:39
 
Fecha de Ingreso: abril-2005
Mensajes: 6
Antigüedad: 19 años
Puntos: 0
mmm, ok...

Supongo que es esto.

int *punts_elimin,*pi,*pf,*flag_aresta,*grup_aresta;
***************************RESERVO****************
pi = ivector(1,numero_de_observaciones);
****************************LIBERO****************
ESTA ES LA INSTRUCCION QUE ME DA PROBLEMAS

-----> free_ivector(pi,1,numero_de_observaciones);

int *ivector(nl,nh)
int nl,nh;
{
int *v;
v=( int *)malloc((unsigned) (nh-nl+1)*sizeof( int));
if (!v) nrerror("allocation failure in ivector()");
return v-nl;
}
void free_ivector(v,nl,nh)
int *v,nl,nh;
{
free((char*) (v+nl));
}
  #10 (permalink)  
Antiguo 26/04/2005, 10:10
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
Mira, puedes postear así que es mejor: Usa [ CODE ] y [/ CODE ] para encerrar código y poder usar tabuladores.

Por cierto, estás usando C antiguo para declarar las funciones. Te corrigo el código para hacerlo "moderno"

free_ivector
Código:
void free_ivector(int * v, int nl, int nh)
{
	free((char*) (v+nl));
}
ivector
Código:
int * ivector(int nl,int nh)
{
	int * v;
	v=(int *) malloc((unsigned)(nh-nl+1)*sizeof(int));
	if (!v) nrerror("allocation failure in ivector()");
	return v-nl;
}

Bueno, realmente en esas funciones no se que haces. Lo primero, pides dos números, nhigh y nlow. La función que crea el vector hace un vector del tamaño (nh-nl+1), luego misteriosamente en vez de devolver (v) devuelves (v-nl), tal que:

Llamamos con (2,6)
Crea vector de tamaño 6-2+1=3
| | | |x|x|x| | |
^ ^
| |___v
|__________direccion devuelta

Y devuelves la posición dos lugares anterior, para que luego vuelva a la posición normal el puntero al llamar a free, extraño pero bien.

Después, otra cosa, el liberador pide el parámtro "nh", pero no le usa. Por otra parte, no sé para que conviertes la dirección resultante en (char *)...

Por último, en malloc haces casting a "unsigned", a pelo, lo cual ahora es incorrecto...

Otra cosa más... La manera que compruebas si el vector ha sido creado correctamente es con if(!v). Eso sólo funciona si NULL está definido como 0, pero... ¿Y si no lo está? Debes comparar con NULL que para eso existe, aunque en muchos casos sea 0.




Todas éstas corecciones están basadas en que estás usando C antiguo, no sé por qué. Pasa a C moderno todo el código primero y luego empieza con las correciones... En teoría esas dos funciones son correctas.
  #11 (permalink)  
Antiguo 26/04/2005, 10:13
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
Otra cosa, toda esa librería ahora está implementada en C++ como plantillas en la STL (Standard Type Library), mucho más versátiles (no hace falta declarar una funciones para cada tipo como en esa librería: free_li, free_i, free_ etc), de cualquier tipo, estructura, clase, con algoritmos y demás... ¿Para qué es el proyecto? Si te obligan a usar esa librería, lo siento de veras . Pero si no, olvídala, eso es arcaico.
  #12 (permalink)  
Antiguo 26/04/2005, 10:55
Avatar de Eternal Idol  
Fecha de Ingreso: mayo-2004
Ubicación: Lucentum
Mensajes: 6.192
Antigüedad: 20 años
Puntos: 74
int *ivector(nl,nh)
int nl,nh;
{
int *v;
v=( int *)malloc((unsigned) (nh-nl+1)*sizeof( int));
if (!v) nrerror("allocation failure in ivector()");
return v-nl;
}
void free_ivector(v,nl,nh)
int *v,nl,nh;
{
free((char*) (v+nl));
}

Esto esta mal, no podes devolver un puntero a memoria que no tenes asignada: v-nl tenes que devolver v que es lo que te asigno el Sistema Operativo y despues liberar v. Si accedes a esa memoria en debug VC++ te la va a señalar el error como en este caso te esta señalando un error.
__________________
¡Peron cumple, Evita dignifica! VIVA PERON CARAJO
  #13 (permalink)  
Antiguo 26/04/2005, 12:17
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
Cita:
Iniciado por Eternal Idol
int *ivector(nl,nh)
int nl,nh;
{
int *v;
v=( int *)malloc((unsigned) (nh-nl+1)*sizeof( int));
if (!v) nrerror("allocation failure in ivector()");
return v-nl;
}
void free_ivector(v,nl,nh)
int *v,nl,nh;
{
free((char*) (v+nl));
}

Esto esta mal, no podes devolver un puntero a memoria que no tenes asignada: v-nl tenes que devolver v que es lo que te asigno el Sistema Operativo y despues liberar v. Si accedes a esa memoria en debug VC++ te la va a señalar el error como en este caso te esta señalando un error.

Es lo que le he dicho, aparte de todas las cosas extrañas que hace. En cualquier caso... Extraño pero en teoría esas dos funciones son correctas.

El fallo que he visto ahora ha sido el siguiente:

Código:
if (!v) nrerror("allocation failure in ivector()");
Ahí sí, detecta que malloc no ha devuelto memoria libre, pero NO haces return. Devuelves el puntero NULL. Mira a ver cómo te indica la librería el último error, que a lo mejor es eso.
  #14 (permalink)  
Antiguo 26/04/2005, 12:21
Avatar de Eternal Idol  
Fecha de Ingreso: mayo-2004
Ubicación: Lucentum
Mensajes: 6.192
Antigüedad: 20 años
Puntos: 74
En teoria son absolutamente incorrectas porque si usa el puntero ese para acceder a memoria esta quebrando toda la logica y puede generar un error de acceso tranquilamente ..

Si ese fuera el error no habria ningun assert de la CRT sino un acceso a memoria invalido (a 0). ¿NULL es diferente de cero en algun compilador?
__________________
¡Peron cumple, Evita dignifica! VIVA PERON CARAJO
  #15 (permalink)  
Antiguo 26/04/2005, 12:35
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
Cita:
Iniciado por Eternal Idol
En teoria son absolutamente incorrectas porque si usa el puntero ese para acceder a memoria esta quebrando toda la logica y puede generar un error de acceso tranquilamente ..

Si ese fuera el error no habria ningun assert de la CRT sino un acceso a memoria invalido (a 0). ¿NULL es diferente de cero en algun compilador?

Me explico: Son correctas si accede a los elementos de otra manera que no sea empezando por v evidentemente.

No lo sé... Pero si pide la memoria, se fia de que ha salido bien y luego la intenta eliminar, al carajo.

En teoría se debe usar NULL... Cierto que hasta ahora no he visto que sea diferente de 0 pero...
  #16 (permalink)  
Antiguo 26/04/2005, 12:40
Avatar de Eternal Idol  
Fecha de Ingreso: mayo-2004
Ubicación: Lucentum
Mensajes: 6.192
Antigüedad: 20 años
Puntos: 74
Por mas que no accediera ... es una chapuza apestosa ...

Si alguien cambia NULL por algo que no sea cero voy y le corto los huevos
__________________
¡Peron cumple, Evita dignifica! VIVA PERON CARAJO
  #17 (permalink)  
Antiguo 26/04/2005, 12:52
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
Cita:
Iniciado por Eternal Idol
Por mas que no accediera ... es una chapuza apestosa ...
Eso no hay duda...


Cita:
Iniciado por Eternal Idol
Si alguien cambia NULL por algo que no sea cero voy y le corto los huevos
Van 5 frases célebres
  #18 (permalink)  
Antiguo 27/04/2005, 07:43
 
Fecha de Ingreso: abril-2005
Mensajes: 6
Antigüedad: 19 años
Puntos: 0
Hola a todos,

Ante todo, muchas gracias por todo. Las funciones ivector, devector etc.. lo unico que hacen es que los arrays vayan de la posicion 1 a la n y no de la 0 a la n. Trabajo con esta libreria por el simple hecho de que el que empezo todo el proyecto empezo utilizandola.

La verdad es que me da muchisimo palo cambiar todas las definiciones de memoria, todos los contadores.... Total , que lo que hare es no liberar los vectores que dan por culo!!!! Es una chapuza, lo se, pero mientras rinda!!!!!

Hasta pronto
  #19 (permalink)  
Antiguo 27/04/2005, 08:55
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
Yo que tú:
1 - Borraba el programa entero.
2 - Borraba la librería.
3 - Me hacía una librería sencilla propia que se lo que hago, o si trabajase en C++, cogía la STL.
4 - Re escribía el programa.

Simple. :) Porque si es para una práctica de universidad y fuera yo el profesor, el código recibiría 0, y si es para un proyecto medianamente serio ten por seguro que tendrás problemas (si es información importante), porque si te falla al liberar es porque el puntero que pasas es erróneo, y por tanto es que enmedio de la aplicación hay algún sitio que está fallando y te va a llevar a errores, cuelgues, pérdidas de datos, etc.

Por cierto, las funciones ésas ya sabemos qué hacen, pero te repetimos que estar usando punteros de dos posiciones más hacia atrás es algo verdaderamente extraño.
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 22:54.