2010-08-29 11 views
7

En mi proyecto tengo un método que crea una cadena a partir de enteros (usando strcat) y lo escribe en un archivo. Desafortunadamente tiene una pérdida de memoria. Mientras rastreaba esa filtración simplifiqué mi código a lo siguiente. Parece que no puedo localizarlo o incluso arreglarlo. Este es el código:¿Dónde está la pérdida de memoria en este código y cómo solucionarlo?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
int main(int argc, char* argv[]) 
{ 
char* output = "\0"; 
int counter = 5; 
    while(counter > 0) 
    { 
     char buffer[20]; 
     sprintf(buffer, "%u", counter); 
     char* temp; 
     temp = malloc((strlen(output) + strlen(buffer) + 1)); 
     strcpy(temp, buffer); 
     strcat(temp, output); 
     char* oldmemory = output; 
     output = temp; 
     free(oldmemory); 
     counter--; 
    } 
printf("output: %s\n", output); 
free(output); 
return 0; 
} 

Valgrind devuelve:

==7125== Memcheck, a memory error detector 
==7125== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. 
==7125== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info 
==7125== Command: ./foo 
==7125== Parent PID: 4455 
==7125== 
==7125== Invalid free()/delete/delete[] 
==7125== at 0x4024B3A: free (vg_replace_malloc.c:366) 
==7125== by 0x8048662: main (foo.c:20) 
==7125== Address 0x8048780 is not stack'd, malloc'd or (recently) free'd 
==7125== 
==7125== 
==7125== HEAP SUMMARY: 
==7125==  in use at exit: 0 bytes in 0 blocks 
==7125== total heap usage: 5 allocs, 6 frees, 20 bytes allocated 
==7125== 
==7125== All heap blocks were freed -- no leaks are possible 
==7125== 
==7125== For counts of detected and suppressed errors, rerun with: -v 
==7125== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 15 from 8) 

¿Dónde está la pérdida de memoria y cómo puedo solucionarlo?

Respuesta

9
#include <stdio.h> 
#include <stdlib.h> 
int main(int argc, char* argv[]) 
{ 
char* output = "\0"; 

Los literales de cadena 'terminan' automáticamente, no es necesario que lo agregue.

int counter = 5; 
    while(counter > 0) 
    { 
     char buffer[20]; 
     sprintf(buffer, "%u", counter); 
     char* temp; 
     temp = malloc((strlen(output) + strlen(buffer) + 1)); 
     strcpy(temp, buffer); 
     strcat(temp, output); 
     char* oldmemory = output; 
     output = temp; 
     free(oldmemory); 

La primera vez que este free() se llama, es liberar el valor inicial de salida, que es un puntero a una cadena literal "\0". Llamar a free() en cualquier cosa que no sea un puntero válido devuelto desde *alloc() o NULL es un comportamiento indefinido.

 counter--; 
    } 
printf("output: %s\n", output); 
free(output); 
return 0; 
} 

informes valgrind:

==7125== Invalid free()/delete/delete[] 
==7125== at 0x4024B3A: free (vg_replace_malloc.c:366) 
==7125== by 0x8048662: main (foo.c:20) 
==7125== Address 0x8048780 is not stack'd, malloc'd or (recently) free'd 

Esto no es una pérdida de memoria; es un inválido free().

+0

+1 para explicaciones claras. – RBerteig

3

Tu aplicación se bloquea al intentar liberar ("\ 0"). (Solo una nota, si quiere una cadena vacía, "" es suficiente, "\ 0" es en realidad la cadena \ 0 \ 0.

En lugar de usar malloc y strcpy, mire en realloc, hace todo lo que quiere pero mejor :) Pero lo más probable es que desee construir su secuencia hacia adelante (contador = 0; contador < 5; contar ++) en lugar de ir hacia atrás

+3

Excepto que la falla de realloc devuelve NULL, por lo que debe observar si hay fugas en el caso en que haga 'p = realloc (p, new_size)'. –

+0

@Roger: fallar 'realloc' probablemente signifique que el programa debe terminar con gracia. No piense que una fuga de memoria es de mucha relevancia. –

+0

No es difícil detectar la fuga potencial con 'realloc', simplemente mantenga una copia del puntero original en la llamada para que pueda liberarse. O, suponga que un 'realloc' que falla significa que es el fin del mundo, y acaba de salir. Personalmente me gusta usar 'assert()' para esa comprobación, ya que se asegura de que la salida sea una falla notable. – RBerteig

4

Su código está roto. En el primer paso, configura oldmemory en la salida donde los puntos de salida a la memoria no se asignaron en el montón. Más tarde, intenta liberar este recuerdo. Esto genera el error de valgrind acerca de liberar memoria que no se asignó a través de malloc. Por lo tanto, la memoria original que asignó nunca se libera.

+0

Creo que él/ella sabe que está roto. No es necesario ser grosero al respecto. –

+0

WTF? ¿Cómo es que lo que escribí es grosero? Creo que tienes tu detector de sensibilidad demasiado alto. O estoy siendo grosero por señalar eso. Quizás ya lo sabes. – sizzzzlerz

+0

No hay necesidad de comenzar aleatoriamente a votar mis preguntas, perra –

1

Si desea utilizar este algoritmo, el espacio inicial para lo que los puntos de salida a deben ser asignados con malloc, de esta manera:

char *output = malloc(1); 
if(!output) { /* handle error */ } 
output[0] = '\0'; 
... rest of code as is ... 

literales de cadena no se asignan con malloc, y por lo tanto no puede ser free 'ed, que es la fuente de tu problema.

Cuestiones relacionadas