Domanda

Sto lavorando per implementare la coda per un incarico. Ho funzionato correttamente ma sembra che stia ricevendo un errore gratuito in momenti casuali.

Non riesco a vederlo, rintracciarlo fino a uno schema o altro oltre che coerente.

Ad esempio, se chiamo il mio programma come " tail -24 test.in " Vorrei ottenere l'errore di checksum errato sulla stessa riga su più corse. Tuttavia, con file diversi e persino diversi numeri di righe da stampare, tornerò senza errori.

Qualche idea su come rintracciare il problema, ho cercato di eseguire il debug per ore senza successo.

Ecco il codice offensivo:

righe è definita come char ** ed è stata malloc come:

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;
}
È stato utile?

Soluzione

La tua routine sta scrivendo oltre il buffer di linea allocato.

La dimensione della linea passata come argomento (cioè "len") probabilmente non include il terminatore NUL. Quando chiami malloc per copiare la linea (cioè "s") devi allocare un byte extra per il terminatore di stringa:

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

Altri suggerimenti

Se riesci a riprodurre in modo coerente il problema con parametri di input specifici, dovresti eseguire il debug in questo modo:

  • Primo debug con l'esattezza gratuita che causa il problema.
  • Quindi capisci quando il ricordo che sta per essere liberato è stato mallocato.
  • Successivamente, esegui il debug nel punto in cui è memorizzata la memoria.
  • Individua nel visualizzatore di memoria il blocco di memoria allocato. Nota sia l'inizio che la fine del blocco. Probabilmente esiste un valore speciale chiamato blocco di protezione appena prima e subito dopo il blocco.
  • Ora scorrere il codice fino a quando la memoria è libera. Ad un certo punto il tuo codice dovrebbe sovrascrivere erroneamente il blocco di protezione. Questa è la dichiarazione offensiva.

Si noti che il problema potrebbe benissimo trovarsi in una parte completamente diversa del programma. Anche se è così gratuito che segnala l'errore, il codice che sovrascrive il blocco di protezione può essere ovunque.

La mia prima domanda è come si calcola len? È solo strlen o include spazio per il terminatore \ 0? Penso che potresti aver superato l'allocazione nella tua strategia. I cattivi comportamenti tenderanno ad accadere sui confini delle parole e appariranno casuali. Inoltre, verifica che le stringhe di origine siano nulle. Se hai commesso un errore sul lato di lettura e non li hai risolti. Quindi strcpy potrebbe sovrascrivere casualmente le cose.

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

Forse prova:

  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... */
  }

In termini di forma generale, ti incoraggio anche ad apportare alcune modifiche stilistiche per rendere il tutto un po 'più leggibile, più facile da seguire e resistente agli errori.

L'aritmetica del puntatore è valida e divertente, ma penso che il tuo intento sia un po 'più chiaro se usi il modulo array come:

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

anziché

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

Ti incoraggio anche a usare meno statica. È abbastanza facile attraversarli in una struttura di dati e passarli nei tuoi accessori e mutatori. Diventa molto più chiaro dove sta accadendo l'azione ti impedisce di fare cose come:

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

dove è possibile introdurre problemi di scoping che sono solo miserabili per il debug.

Nline e numline hanno lo stesso valore?

Il chiamante di insert_line consente spazio per il NUL finale quando passa la lunghezza nel secondo parametro?

Non sono sicuro che sia correlato, ma queste due righe mi sembrano sospette:

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

Prima assegni il ritorno di malloc a righe [slot] e poi controlli (righe + slot) , se quest'ultimo era NULL, avresti avuto la dereference a NULL puntatore!

Anche se le righe [slot] (il tuo * (righe + slot)) non è nullo, perderai memoria quando gli assegnerai il risultato di malloc ().

Suppongo che righe sia un carattere * righe [] `e che lo slot sia all'interno del limite consentito!

Concordo con il sospetto di Remo su quelle due righe, ma non sulla tangente che Remy ha avuto. Dobbiamo condividere il credito per aver trovato questo errore.

*(lines + slot) = some value
if((lines + slot) == NULL) then die
should be
if(*(lines + slot) == NULL) then die
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top