Pregunta

Estoy trabajando en la implementación de tail para una tarea. Lo tengo funcionando correctamente, sin embargo, parece que recibo un error de forma gratuita en momentos aleatorios.

No puedo ver, para rastrear hasta un patrón o cualquier otra 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 incorrecto en la misma línea en varias ejecuciones. Sin embargo, con diferentes archivos e incluso diferentes números de líneas para imprimir, volveré sin errores.

Cualquier idea sobre cómo localizar el problema, he estado intentando depurarlo durante horas sin ningún resultado.

Aquí está el código ofensivo:

las líneas se definen como un char ** y fueron 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;
}
¿Fue útil?

Solución

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

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

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

Otros consejos

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

  • Primero realice la depuración en el archivo exacto que cause el problema.
  • Luego averigua cuándo la memoria que está a punto de liberarse fue mal colocada.
  • A continuación, depure el lugar donde la memoria está mal asignada.
  • Localice en el visor de memoria el bloque de memoria asignado. Tenga en cuenta tanto el inicio como el final del bloque. Probablemente haya un valor especial llamado bloque de protección justo antes y justo después del bloque.
  • Ahora recorra el código hasta que se libere la memoria. En algún momento, su código debería sobrescribir por error 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. Aunque es gratis lo que informa el error, el código que sobrescribe el bloque de protección puede estar en cualquier lugar.

Mi primera pregunta es ¿cómo se calcula len? ¿Es solo strlen o incluye espacio para el terminador \ 0? Creo que puede estar excediendo su asignación en su estrategia. La mala conducta tenderá a ocurrir en los límites de las palabras y aparecerá al azar. Además, verifique que las cadenas de origen terminen en nulo. Si cometió un error en el lado de lectura y no los terminó. Entonces, Strcpy puede estar sobrescribiendo cosas al azar.

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

Quizás intente:

  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 generales, también lo alentaría a hacer algunos cambios estilísticos para hacer que todo sea un poco más legible, más fácil de seguir y resistente a los errores.

La aritmética de punteros es válida y divertida, pero creo que tu intención es un poco más clara si usas la forma de matriz como:

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

en lugar de

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

También te animo a que uses menos estadísticas. Es bastante fácil atravesarlos en una estructura de datos y pasarlos a sus accesores y mutadores. Se vuelve mucho más claro dónde ocurre la acción que le impide hacer cosas como:

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

donde puede introducir problemas de alcance que son simplemente miserables para depurar.

¿Las líneas y las líneas numéricas tienen el mismo valor?

¿El interlocutor de insert_line deja espacio para el NUL final al pasar la longitud en el segundo parámetro?

No estoy seguro de que esté relacionado, pero estas dos líneas me parecen sospechosas:

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

Primero asigna el retorno de malloc a líneas [slot] y luego verifica (líneas + slot) , si esta última era NULL, tuvo una desreferencia a NULL puntero!

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 líneas es un char * líneas [] `¡y la ranura está dentro del límite permitido!

Estoy de acuerdo con la sospecha de Remo acerca de esas dos líneas, pero no con la tangente con la que se disparó Remo. 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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top