2013-05-24 7 views
6

Questi 2 errori sono in arrivo con un elenco collegato/programma di lettura/strtok di file di basso livello.C: Valgrind: utilizzo del valore non inizializzato della dimensione 4 E Utilizzo del valore non inizializzato della dimensione 4

==10982== Use of uninitialised value of size 4 
==10982== at 0x40C3899: strtok (strtok.S:197) 
==10982== by 0x8048719: main (main.c:9) 
==10982== Uninitialised value was created by a stack allocation 
==10982== at 0x80487D2: buildList (functions.c:13) 
==10982== 
==10982== Use of uninitialised value of size 4 
==10982== at 0x40C38C1: strtok (strtok.S:223) 
==10982== by 0x8048719: main (main.c:9) 
==10982== Uninitialised value was created by a stack allocation 
==10982== at 0x80487D2: buildList (functions.c:13) 
==10982== 
==10982== Conditional jump or move depends on uninitialised value(s) 
==10982== at 0x40C38C4: strtok (strtok.S:224) 
==10982== by 0x8048719: main (main.c:9) 
==10982== Uninitialised value was created by a stack allocation 
==10982== at 0x80487D2: buildList (functions.c:13) 

Ecco la funzione buildList

void buildList(int fdin, int lines) 
{ 
    char ara[4096]; 
    int num; 
    double p; 
    read(fdin, ara, 4096); 
    char *nl = "\n"; 
    char *ws = " "; 
    char *temp = strtok(ara, " "); 
    while(temp != NULL) 
    { 
     Stock *s = (Stock*)calloc(1, sizeof(Stock)); 
     s->c.symbol = (char*)calloc(strlen(temp)+1, sizeof(char)); 
     strcpy(s->c.symbol, temp); 
     temp = strtok(NULL, "\n"); 
     s->c.name = (char*)calloc(strlen(temp)+1, sizeof(char)); 
     strcpy(s->c.name, temp); 
     temp = strtok(NULL, "\n"); 
     sscanf(temp, "%lf", &p); 
     temp = strtok(NULL, "\n"); 
     s->price = p; 
     sscanf(temp, "%d", &num); 
     s->shares = num; 
     Node *n = (Node*)calloc(1, sizeof(Node)); 
     n->data = s; 
     addOrdered(n); 
     temp = strtok(NULL, " "); 
    } 
    close(fdin); 
} 

non riesco a capire il motivo per cui si verifica questo errore. Da quello che ho letto è perché sto assegnando le cose a un char * da strtok senza assegnare loro alcun ricordo. Comunque è così che l'ho fatto in passato e penso che sia andato bene.

+0

Qual è la riga 13 di functions.c? – aschepler

+0

Sembra che a Valgrind manchi il fatto che 'ara' venga" inizializzato "da' read() '. Solo per i sorrisi, prova a mettere qualcosa come "memset (ara, 0, sizeof (ara))" proprio prima della lettura, e vedi se questo sopprime l'avvertimento. Se lo fa, rimuovilo e sappi che puoi tranquillamente ignorare l'avviso (o scoprire come far arrestare Valgrind). Ovviamente anche 'read()' potrebbe non funzionare, nel qual caso Valgrind è corretto. –

+0

Non si fornisce la definizione di 'main', né si mostra l'input che sta causando il problema. Né si esegue alcun controllo degli errori in nessuna parte del codice precedente. Si prega di creare un [SSCCE] (http://sscce.org) che non ci richiede di indovinare! –

risposta

1

I dati letti da read hanno un terminatore null alla fine? In caso contrario, probabilmente è questo il problema.

4

Come altri hanno ipotizzato, valgrind si lamenta che lo strtok utilizza la memoria non inizializzata. La questione diventa allora perché, in quanto sembra che viene inizializzato da:

read(fdin, ara, 4096); 

Tuttavia, read() non significa \0 terminare i dati, mentre strtok aspetta una stringa terminata \0. Assicurarsi che l'ingresso sia terminato correttamente:

ssize_t result = read(fdin, ara, sizeof[ara]-1); /* leave room for '\0' */ 
ara[result > 0 ? result : 0] = '\0'; 

Il memset(ara, 0, sizeof(ara)); suggerimento di Lee Daniel Crocker è lo stesso tipo di correzione, ma funziona solo se il file contiene meno di sizeof(ara) byte di ingresso. Sei ancora esposto a un problema simile se il file che leggi ha 4096 byte di dati o più. Quindi, strtok verrà forzato a eseguire la scansione oltre la fine del buffer per cercare lo \0, che porta a un comportamento non definito.

+0

Ma la chiamata a 'strtok' di cui si lamenta è in' main', non nella funzione sopra ... –

+0

@OliCharlesworth: Penso che sia solo perché la funzione è stata sottolineata. – jxh

+0

@OliCharlesworth Non uso strtok ovunque nel main. –

3

read(fdin, ara, 4096);

... che potrebbe tornare:

  • -1, cioè la lettura ottenuto un errore, e ara non è stato compilato;
  • 0, significa che hai raggiunto la fine del file e che ara non è stato compilato;
  • un valore < 4096, significa che ci sono meno di 4096 byte lasciati nel file, e non tutti i byte di ara sono riempiti.

Controllare sempre il valore di ritorno di read().

char * temp = strtok (ara, "");

$ man strtok 

...

The strtok() function is used to isolate sequential tokens in a null-ter- 
minated string, str. ... 

Non c'è assolutamente nulla che garantisca che ara ha un carattere null ('\0') in esso, in modo da poter non validamente mano a strtok(). Rendilo char ara[4097] e fai ara[4096] = '\0'; dopo la lettura se vuoi assicurarti che ci sia un '\0' in esso.

O, meglio ancora, se il valore di ritorno read() s' è in una variabile data_read, e hai già controllata per assicurarsi che non è -1, fare ara[data_read] = '\0';, in modo che si imposta il byte dopo l'ultima lettura per '\0'.

E cosa succede se il file ha più di 4096 caratteri, e la chiamata read() si legge, ad esempio, diverse linee e l'inizio di un'altra linea? Detto questo, potresti prendere in considerazione l'utilizzo di fopen() per aprire il file e utilizzare fgets() per leggere le righe.

Problemi correlati