Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Error con free

Estas en el tema de Error con free en el foro de C/C++ en Foros del Web. Buenas, estaba haciendo un programilla que buscara ficheros acabdos en ~, pero hay un problema. Primero les enganchare el codigo y luego lo comento: Código: ...
  #1 (permalink)  
Antiguo 25/03/2008, 10:42
 
Fecha de Ingreso: marzo-2008
Mensajes: 37
Antigüedad: 16 años, 1 mes
Puntos: 0
Error con free

Buenas, estaba haciendo un programilla que buscara ficheros acabdos en ~, pero hay un problema. Primero les enganchare el codigo y luego lo comento:

Código:
void buscar(char *home,const char *destino)
{
  DIR *dirp;
  struct dirent *dir;
  int fd,i,de,ds,nbytes;
  char *duplicado;
  char *pathdest;
  char *pathhome;
  char buffer[BUFSIZ];

                        if((dirp=opendir(home))==NULL)
                          {
                            perror(home);
                            exit(-1);
                          }

            
        
          if((pathdest=(char *)calloc(80,sizeof(char)))==NULL)
                           {
                              perror("malloc");
                              exit(-1);
                           }

                         if((pathhome=(char *)calloc(80,sizeof(char)))==NULL)
                           {
                              perror("malloc home");
                              exit(-1);
                           }
                     printf("memoria reservada\n");
     
                    while((dir=readdir(dirp))!=NULL)
                      {
       
                         
                
               printf("empezando while\n");
       
                         duplicado=strdup(dir->d_name);

                            for(i=strlen(dir->d_name)-1;i>0;i--)
                               if(duplicado[i]=='~')
	                         {
                                  
	                          pathhome=(char *)realloc(pathhome,((strlen(home))+((strlen(dir->d_name)))));
                                  pathdest=(char *)realloc(pathdest,((strlen(destino))+((strlen(duplicado)))));
             
                                  
                                   sprintf(pathhome,"%s/%s",home,duplicado);
	                           sprintf(pathdest,"%s/%s",destino,duplicado);
                                   
                
                                    if((fd=creat(pathdest,0666))==-1)
         	                     {
	                              perror(pathdest);
		                      exit(-1);
		                     }
            
		                   if((de=open(pathhome,O_RDONLY))==-1)
                                     {
			              perror(pathhome);
                                      exit(-1);
		                     }
                   
		                   if((ds=open(pathdest,O_WRONLY))==-1)
		                     {
                                      perror(pathdest);
                                      exit(-1);
                                     }
                      
		                 while((nbytes=read(de,buffer,sizeof(buffer)))>0)
		                   if((write(ds,buffer,nbytes))!=nbytes)
                                   fprintf(stderr,"Error de escritura en %s\n",ds);
          
        
		                    close(de);
                                    close(ds);

		                   if((unlink(pathhome))==-1)
		                    {
                                      perror(pathhome);
                                      exit(-1);
                                    }
                        // printf("petando aqui\n");
                                      
            
	                      }
                               //printf("hola\n");
                                
                   printf("repitiendo while\n");
	           }
      printf("acabando\n");
      
  
  closedir(dirp);
  free(source);
 printf("source liberado\n");
  free(destdir);
  printf("des liberado\n");
  free(pathdest);
  printf("pathdest liberado\n");
  free(duplicado);
  printf("duplicado liberado\n");
  free(pathhome);
  printf("pathhome liberado\n"); 
  }
El error esta en free(pathhome), ya que me peta ahi, cuando libero la memoria de pathhome. Como ven primero le asigno 80 bytes al empezar el programa, luego cada vez que se encuentra un fichero acabado en ~, le reasigno la lontigud del directorio mas la del nombre del fichero, y bueno, todo va bien hasta el momento de liberar la memoria que acaba con un:

*** glibc detected *** ./backups: free(): invalid next size (fast): 0x0804c0c8 ***
======= Backtrace: =========
/lib/i686/cmov/libc.so.6[0xb7e9b915]
/lib/i686/cmov/libc.so.6(cfree+0x90)[0xb7e9f380]
./backups[0x8049092]
./backups[0x8048cb0]
/lib/i686/cmov/libc.so.6(__libc_start_main+0xe0)[0xb7e46450]
./backups[0x80487f1]
======= Memory map: ========
08048000-0804a000 r-xp 00000000 08:06 639238 /home/null/mis_programas/backups
0804a000-0804b000 rw-p 00001000 08:06 639238 /home/null/mis_programas/backups
0804b000-0806c000 rw-p 0804b000 00:00 0 [heap]
b7d00000-b7d21000 rw-p b7d00000 00:00 0
b7d21000-b7e00000 ---p b7d21000 00:00 0
b7e15000-b7e21000 r-xp 00000000 08:02 354860 /lib/libgcc_s.so.1
b7e21000-b7e22000 rw-p 0000b000 08:02 354860 /lib/libgcc_s.so.1
b7e2f000-b7e30000 rw-p b7e2f000 00:00 0
b7e30000-b7f77000 r-xp 00000000 08:02 370991 /lib/i686/cmov/libc-2.7.so
b7f77000-b7f78000 r--p 00147000 08:02 370991 /lib/i686/cmov/libc-2.7.so
b7f78000-b7f7a000 rw-p 00148000 08:02 370991 /lib/i686/cmov/libc-2.7.so
b7f7a000-b7f7d000 rw-p b7f7a000 00:00 0
b7f89000-b7f8c000 rw-p b7f89000 00:00 0
b7f8c000-b7fa8000 r-xp 00000000 08:02 354818 /lib/ld-2.7.so
b7fa8000-b7faa000 rw-p 0001b000 08:02 354818 /lib/ld-2.7.so
bfb95000-bfbaa000 rw-p bfb95000 00:00 0 [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
Abortado


El error es : " free(): invalid next size (fast): 0x0804c0c8", y como ven todo va bien hasta que se intenta liberar su memoria:

acabando
source liberado
des liberado
pathdest liberado
duplicado liberado


Peta ahi. La verdad no se que estoy haciendo mal, si alguien pudiera ayudarme... se lo agradeceria mucho.

Gracias de antemano
  #2 (permalink)  
Antiguo 25/03/2008, 11:06
Avatar de Mephisto  
Fecha de Ingreso: enero-2006
Ubicación: Mexico DF
Mensajes: 184
Antigüedad: 18 años, 4 meses
Puntos: 3
Re: Error con free

De manera particular, casi no me gusta usar free ya que me encontraba problemas como los que mencionas, en vez de hacer eso, lo que hago es a traves de un memset limpiar el espacio de memoria que emplee para no dejar basura y despues referencio el apuntador a NULL. No se si esto te pudiera servir.

Por otro lado, pudieras debuggear el prog para que cheques si en el momento que reasignas la memoria al apuntador no se esta encimando con otro, eso tambien es una razon por la cual puede estar tronando...
__________________
Saludos...

Todos somos sabios, solo que en diferentes disciplinas...
  #3 (permalink)  
Antiguo 25/03/2008, 11:51
Avatar de aloqui  
Fecha de Ingreso: diciembre-2007
Mensajes: 973
Antigüedad: 16 años, 5 meses
Puntos: 24
Re: Error con free

Cita:
Iniciado por Leber Ver Mensaje
Peta ahi. La verdad no se que estoy haciendo mal, si alguien pudiera ayudarme... se lo agradeceria mucho.

Gracias de antemano
Para lo que estás haciendo en realidad no es impresdincible memoria dinámica ya que estás reutilizando dentro del bucle la misma variable (con distinto tamaño) una y otra vez.
Para estos casos es mas recomentable utilizar memoria estática (local o global) que dimensiones suficientemente grande para manejar los nombres mas largos (directorio+fichero). Por ejemplo con 500 carácteres creo que tienes suficiente.
Además de que ya no te va a fallar, el código queda mucho más simple y de propina
te funcionará más rápido.

Cita:
Iniciado por Mephisto Ver Mensaje
De manera particular, casi no me gusta usar free ya que me encontraba problemas como los que mencionas, en vez de hacer eso, lo que hago es a traves de un memset limpiar el espacio de memoria que emplee para no dejar basura y despues referencio el apuntador a NULL. No se si esto te pudiera servir.
No te ofendas, pero eso es una chapuza. Vas dejando memoria sin liberar continuamente, si lo haces en un programa que maneje muchos datos, al final te quedas sin memoria.
__________________
Grupos de Música
Pop Music Stars
  #4 (permalink)  
Antiguo 25/03/2008, 12:16
Avatar de _Lucifer_  
Fecha de Ingreso: junio-2006
Mensajes: 1.662
Antigüedad: 17 años, 11 meses
Puntos: 28
Re: Error con free

No sé exactamente cual es el error, pero sé que ese error aparece cuando intentas liberar memoria no reservada, es decir:

Código:
#include <stdlib.h>
int main()
{
   int *ptr;
   free(ptr);
   return 0;
}
Esto debería generar el mismo error (o muy parecido), así que probablemente el puntero pathhome queda "apuntando" a una posición que no puedes liberar.

Sea cual sea la solución que decidas usar NO hagas esto:
Cita:
...
De manera particular, casi no me gusta usar free ya que me encontraba problemas como los que mencionas, en vez de hacer eso, lo que hago es a traves de un memset limpiar el espacio de memoria que emplee para no dejar basura y despues referencio el apuntador a NULL. No se si esto te pudiera servir.
...
@Mephisto: no importa si llenas la memoria de 0's, 1's, 12354's...si está reservada previamente con malloc quedará reservada y no se podrá usar por tu programa ni por ningún otro porque además estas perdiendo la ubicación cuando asignas NULL.

Saludos
__________________
Si crees que no tiene sentido, etonces probablemente lo tenga... :arriba:
  #5 (permalink)  
Antiguo 25/03/2008, 12:50
Avatar de Mephisto  
Fecha de Ingreso: enero-2006
Ubicación: Mexico DF
Mensajes: 184
Antigüedad: 18 años, 4 meses
Puntos: 3
Re: Error con free

Cita:
No te ofendas, pero eso es una chapuza

Cita:
Sea cual sea la solución que decidas usar NO hagas esto:
Claro que no me ofendo, al contrario, no lo había observado desde la perspectiva que plantean ambos y tienen toda la razon, cuando sea un programa grande habrá mucho desperdicio de memoria...

Lo que haré será evitar esa practica que tenía, lo unico es que si es que del problema original de Leber pudiera ser que se le estan encimando los apuntadores en la reasignación de memoria y se presenta el problema que menciona Lucifer...
__________________
Saludos...

Todos somos sabios, solo que en diferentes disciplinas...
  #6 (permalink)  
Antiguo 25/03/2008, 13:40
 
Fecha de Ingreso: marzo-2008
Mensajes: 37
Antigüedad: 16 años, 1 mes
Puntos: 0
Re: Error con free

Al final vi el error, buf, llevo con esto 2 dias, ya que hacia hecho uno del mismo modo empleando realloc y me sorprendia que ahora no funcionase.

Tiene gracia la cosa, pero el error estaba aqui:

pathhome=(char *)realloc(pathhome,((strlen(home))+((strlen(duplic ado)))));

Tras un error que me lanzo realloc de "invalid next size", me dio que pensar, y la solucion era reasignarle la longitud del directorio+elfichero+2 bytes mas(supongo que sera del '\0') Y ya esta, todo arreglado ahora hare mas pruebas por si un caso.

De todos modos muchisimas gracias a todos, da gusto estar aqui.

Un saludo
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 03:05.