2015-05-28 17 views
5

Sto cercando di verificare questo file di codice test.c seguito utilizzando valgrind, quando faccio prova test.c gcc -o ottengo l'errore followValgrind errore M64 M32

Syscall param write(buf) points to uninitialised byte(s) 
==22765== at 0x4F22870: __write_nocancel (syscall-template.S:81) 
==22765== by 0x4EB0002: [email protected]@GLIBC_2.2.5 (fileops.c:1261) 
==22765== by 0x4EB14DB: [email protected]@GLIBC_2.2.5 (fileops.c:538) 
==22765== by 0x4EB0D5F: [email protected]@GLIBC_2.2.5 (fileops.c:165) 
==22765== by 0x4EA4B0F: [email protected]@GLIBC_2.2.5 (iofclose.c:59) 
==22765== by 0x400986: main (in /home/grados-sanchez/git/merkle-codigos-C/test) 
==22765== Address 0x4025770 is not stack'd, malloc'd or (recently) free'd 
==22765== Uninitialised value was created by a stack allocation 
==22765== at 0x4007E2: node_write (in /home/grados-sanchez/git/merkle-codigos-C/test) 

ma quando corro gcc test.c -o test e poi valgrind non ho alcun errore. La mia domanda è: cosa succede con valgrind in questo caso? Esiste un modo per eseguire valgrind per 32 o 64 bit?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define id_lenght 6000 
typedef unsigned char * ustring; 
typedef struct { 
    ustring ustr; 
    int height; 
    char id[id_lenght]; 
} node; 

int validation_read(void * ptr_var, size_t sizeof_datatype, int num, 
    FILE * ptr_file) { 
    if (fread(ptr_var, sizeof_datatype, num, ptr_file) <= 0) { 
     printf("Error reading file"); 
     return 1; 
    } 
return 0; 
} 

void node_read(FILE * node_ptr, node * n, int r) { 
    int i; 
    validation_read(n->id, sizeof(unsigned char), id_lenght, node_ptr); 
    validation_read(&(n->height), sizeof(int), 1, node_ptr); 
    validation_read(n->ustr, sizeof(unsigned char) * (r + 1), 1,node_ptr); 
} 

void node_init(node * n, int r) { 
    memset(n, 0, sizeof(node)); 
    n->ustr = malloc((r + 1) * sizeof(unsigned char)); 
    memset(n->ustr, 0, (r + 1)); 
    n->ustr[r] = 0; 
    n->height = -1; 
    memset(n->id,0,id_lenght+1); 
} 


void node_write(FILE * node_ptr, node * n, int r) { 
    int i; 
    char newid[id_lenght]; 
    memset(newid,0,id_lenght); 
    sprintf(newid,"%s",n->id); 
    fwrite(newid, sizeof(char), id_lenght+1, node_ptr); 
    fwrite(&(n->height), sizeof(int), 1, node_ptr); 
    fwrite(n->ustr, sizeof(unsigned char) * (r + 1), 1,node_ptr); 
} 


void node_destroy(node * n) { 
    free(n->ustr); 
    n->height = -1; 
} 

int main(){ 
    FILE * ptr = fopen("juantest","w+"); 
    int r = 64/8; 
    node in; 
    node_init(&in, r); 
    node_write(ptr, &in, r); 
    node_destroy(&in); 
    fclose(ptr); 
} 

EDIT Ma un problema si verifica quando si cerca di leggere il file. Ho modificato il mio codice sopra. Ottengo Errore durante la lettura di file Errore durante la lettura del file. Errore di lettura

+0

Il tuo codice non è leggibile, perfavore formattalo! E 'sizeof (char) == 1' per definizione. –

+1

Il tuo "file di lettura degli errori" che appare 3 volte deve significare che non c'è nulla * scritto * nel file, o che stai scrivendo sul file e provi immediatamente a leggerlo. – usr2564301

+0

in funzione: node_read() e in funzione: node_write(): ognuna di queste funzioni ha una variabile sullo stack: 'i' che non viene utilizzato. Suggerisci 1) rimuovi quelle due variabili. 2) abilitare tutti gli avvertimenti durante la compilazione e correggere quegli avvertimenti (dopotutto, il compilatore conosce il linguaggio C molto meglio di te o di me.) – user3629249

risposta

6

Valgrind ha ragione di preoccuparsi. In questa riga

fwrite(newid, sizeof(char), id_lenght+1, node_ptr); 

si sta scrivendo 1 byte più dati di quelli consentiti; quello oltre la nuova stringa di stack temporanea. Probabilmente confuso scrivendo una stringa (con un +1 per la terminazione zero) con la scrittura esattamente la (massimo) dimensione del buffer usato:

fwrite(newid, sizeof(char), id_length, node_ptr); 

Dal momento che sono il dump il contenuto della memoria in un file, lei ha ragione per cancellare la stringa memoria prima di utilizzare sprintf. Non sai mai cosa c'è nella memoria appena assegnata!
Si noti che, se si è preoccupati dell'integrità dei dati, è sempre preferibile utilizzare la variante sicura sprintf_s, poiché proteggerà l'utente da questo sovraccarico.

+1

ma voglio scrivere un array di lunghezza fissa newid – Juan

+0

@Juan: fair point (ed ero chiedendosi come hai letto quella stringa!). Ho invertito la mia risposta e un +1 per te per cancellare la stringa prima di scrivere su disco. Ma controlla le funzioni '_s' per sicurezza. Inoltre, per favore usa ALL_CAPS per '# define's - è una convenzione ma piuttosto forte. – usr2564301

+0

Modifica la mia domanda ... – Juan