2008-10-24 10 views
9

Estoy trabajando en la implementación de cola para una tarea. Lo tengo funcionando correctamente, pero parece que recibo un error de forma gratuita en momentos aleatorios.Malloc Error: suma de comprobación incorrecta para el objeto liberado

No puedo ver, rastrearlo hasta un patrón o cualquier cosa que no sea consistente.

Por ejemplo, si llamo a mi programa como "tail -24 test.in", obtendría el error de suma de comprobación incorrecta en la misma línea en varias ejecuciones. Sin embargo, con diferentes archivos e incluso diferentes números de líneas para imprimir, regresaré sin errores.

Cualquier idea sobre cómo rastrear el problema, he estado intentando depurarlo durante horas en vano.

Aquí está el código erróneo:

líneas se define como un char ** y fue malloc como:

lines = (char**) malloc(nlines * sizeof(char *)); 

void insert_line(char *s, int len){ 

    printf("\t\tLine Number: %d Putting a %d line into slot: %d\n",processed,len,slot); 
    if(processed > numlines -1){//clean up 
    free(*(lines+slot)); 
    *(lines + slot) = NULL; 
    } 
    *(lines + slot) = (char *) malloc(len * sizeof(char)); 
    if(*(lines + slot) == NULL) exit(EXIT_FAILURE); 
    strcpy(*(lines+slot),s); 
    slot = ++processed % numlines; 
} 
+0

¿tiene ranura 0 o 1? ranura nunca excede nlines-1, ¿correcto? – Dre

+0

a la derecha el módulo vuelve automáticamente a 0 – None

+0

¿Qué compilador y qué depurador estás usando? Dependiendo de eso, es posible que puedan brindar ayuda para depurar su problema. –

Respuesta

7

Su rutina está escribiendo más allá del búfer de línea asignado.

El tamaño de la línea pasada como argumento (es decir, "len") probablemente no incluya el terminador NUL. Cuando llama a malloc para copiar la línea (es decir, "s"), necesita asignar un byte adicional para el terminador de cadena:

*(lines + slot) = (char *) malloc((len + 1) * sizeof(char)); 
+3

¿Cómo se aceptó esta respuesta? Un día antes de que se publicara esta respuesta, el póster original comentó mi respuesta, diciendo "El nulo se explica por la función de llamada". –

0

hacer nLines y numlines tener el mismo valor?

¿La persona que llama de insert_line deja espacio para el NUL posterior al pasar la longitud en el segundo parámetro?

+0

sí, nlines y numlines tienen el mismo valor. la declaración de línea en realidad ocurre en otro lugar. El nulo es contabilizado por la función de llamada. – None

0

no estoy seguro de que está relacionado, pero estas dos líneas parece sospechoso para mí:

*(lines + slot) = (char *) malloc(len * sizeof(char)); 
    if((lines + slot) == NULL) exit(EXIT_FAILURE); 

asignar primero el retorno de malloc a lines[slot] y luego comprobar (lines+slot), si éste era NULL, que tenía Desreferencia un puntero NULL!

También si las líneas [ranura] (su * (líneas + ranura)) no son nulas, perderá memoria cuando le asigne el resultado de malloc().

Supongo que lines es un char * lines [] `¡y la ranura está dentro del límite permitido!

0

Estoy de acuerdo con la sospecha de Remo sobre esas dos líneas, pero no sobre la tangente que remo se activó. Deberíamos compartir el crédito por encontrar este error.

*(lines + slot) = some value 
if((lines + slot) == NULL) then die 
should be 
if(*(lines + slot) == NULL) then die 
+0

Oye, editó su código fuente mientras editaba esta respuesta. En ese caso su error probablemente esté en alguna otra parte del programa que aún no ha editado ... –

+0

ya lo había arreglado ... eso no es lo que está causando mi error de malloc – None

3

Si puede reproducir constantemente el problema con los parámetros de entrada específicos, debe depurar la siguiente manera:

  • Primera de depuración en el exacto libre que causa el problema.
  • A continuación, descubra cuando la memoria que está a punto de liberarse estaba malloc'ed.
  • A continuación, depure hasta el lugar donde la memoria está malloc'ed.
  • Localice en el visor de memoria el bloque asignado de memoria. Tenga en cuenta tanto el inicio como el final del bloque. Probablemente haya un valor especial llamado bloque de guardia justo antes y justo después del bloque.
  • Ahora revise el código hasta que la memoria esté libre. En algún punto su código debería sobrescribir erróneamente el bloque de protección. Esa es la declaración ofensiva.

Tenga en cuenta que el problema podría estar en una parte completamente diferente de su programa. A pesar de que es este libre que informa el error, el código que sobrescribe el bloque de guardia puede estar en cualquier lugar.

+0

El nulo está incluido, el El código que está viendo es el único lugar donde opero el puntero. Muy raro. – None

+0

Algún otro código podría estar escribiendo fuera de su memoria asignada y en los valores de protección alrededor de su bloque.Es por eso que necesitas pasar por todo el código entre Malloc y Free. En algún momento, algún código sobrescribirá uno de los valores de protección. –

1

Mi primera pregunta es ¿cómo se calcula len? ¿Es solo strlen o incluye espacio para el terminador \ 0? Creo que puede sobrepasar su asignación en su strcpy. El mal comportamiento tenderá a ocurrir en los límites de las palabras y aparecerá al azar. Además, verifique para asegurarse de que sus cadenas fuente están terminadas en nulo. Si cometió un error en el lado de lectura y no los terminó. Entonces strcpy puede estar sobreescribiendo cosas al azar.

*(lines + slot) = (char *) malloc(len * sizeof(char)); 
    if(*(lines + slot) == NULL) exit(EXIT_FAILURE); 
    strcpy(*(lines+slot),s); 

quizás prueba:

lines[slot] = (char *) malloc((len + 1) * sizeof(char)); 
    if(lines[slot] == NULL) exit(EXIT_FAILURE); 
    if(strlen(s) <= len){ 
    strcpy(lines[slot],s); 
    } 
    else{ 
    /* do something else... */ 
    } 

En términos de forma general, también me animo a hacer algunos cambios de estilo para hacer que todo sea un poco más fácil de leer, fácil de seguir y resistente a errores

puntero aritmética es válida y divertido, pero creo que su intención es un poco más clara si se utiliza la forma matricial como:

free(lines[slot]); 
lines[slot] = NULL; 

en lugar de

free(*(lines+slot)); 
*(lines + slot) = NULL; 

yo también animo usted para usar menos estática. Es bastante fácil atravesarlos en una estructura de datos y pasarlos a sus accessors y mutators. Se vuelve mucho más clara que la acción que está sucediendo le impide hacer cosas como:

static int numlines = 0; 
void insert_line(char *s, int len){ 
    int numlines = 5; 

donde se pueden introducir los temas de alcance que son igual de miserables de depurar.

Cuestiones relacionadas