2010-09-05 4 views
4

J'ai créé une classe de liste chaînée, mais cette fonction génère des erreurs de type valgrind, indiquant qu'il existe un saut conditionnel basé sur une valeur non initialisée dans cette fonction. Je ne suis pas exactement sûr de ce que je dois faire pour le réparer. Il y a essentiellement une classe de nœuds pour la liste chaînée et c'est l'itération sur tous les nœuds vérifiant si le paramètre clé correspond à un nœud préexistant et s'il le renvoie la valeur.Valgrind Valeurs non initialisées (création d'une structure de données de liste chaînée)

const char *dictionary_get(dictionary_t *d, const char *key) 
{ 

node* current; 
current = d->head; 
if(strcmp(current->key,key)==0) 
     return current->value; 
while(current->next != NULL){ 
     current = current->next; 
     if(current!=NULL && strcmp(current->key,key)==0) 
       return current->value; 
} 

     return NULL; 
}  

Des idées?


J'ai suivi avec des origines réexaminé de valgrind et c'est la sortie:

==25042== Conditional jump or move depends on uninitialised value(s) 
==25042== at 0x4A06E6A: strcmp (mc_replace_strmem.c:412) 
==25042== by 0x400DD6: dictionary_get (libdictionary.c:143) 
==25042== by 0x400826: main (part2.c:84) 
==25042== Uninitialised value was created by a stack allocation 
==25042== at 0x400AE3: dictionary_parse (libdictionary.c:69) 
==25042== 
==25042== Conditional jump or move depends on uninitialised value(s) 
==25042== at 0x4A06E8A: strcmp (mc_replace_strmem.c:412) 
==25042== by 0x400DD6: dictionary_get (libdictionary.c:143) 
==25042== by 0x400826: main (part2.c:84) 
==25042== Uninitialised value was created by a stack allocation 
==25042== at 0x400AE3: dictionary_parse (libdictionary.c:69) 
==25042== 
==25042== Conditional jump or move depends on uninitialised value(s) 
==25042== at 0x400DD9: dictionary_get (libdictionary.c:143) 
==25042== by 0x400826: main (part2.c:84) 
==25042== Uninitialised value was created by a stack allocation 
==25042== at 0x400AE3: dictionary_parse (libdictionary.c:69) 

On dirait que cela pourrait venir de dictionary_parse donc je vais aussi poster cette fonction.

int dictionary_parse(dictionary_t *d, char *key_value) 
    { 
char* colon; 
char* space; 
colon = key_value; 
space = key_value; 

space++; 

int key_length = -1; //Default key length to check for failure 

int i=0; 
int j=0; // Loop variables 
int k=0; 

int length = strlen(key_value); 

for(i=0;i<length-2;i++){ 
     if(*colon == ':' && *space == ' '){ 
       key_length = i; 
       break; 
     } 
     colon++; 
     space++; 
} 

if(key_length == -1 || key_length == 0) 
     return -1; 

int value_length = length-2-key_length; 

colon = key_value; 


char key_word[key_length]; 
key_word[0] = '\0'; 
char value_word[value_length]; 
value_word[0] = '\0'; 

for(j=0;j<key_length;j++){ 
key_word[j] = *colon; 
colon++; 
} 

space++;  

for(k=0; k<value_length;k++){ 
value_word[k] = *space; 
space++; 
    } 
char* finalkey[key_length]; 
strcpy((char*)finalkey,key_word); 
char* finalvalue[value_length]; 
strcpy((char*)finalvalue,value_word); 

dictionary_add(d,(char*)finalkey,(char*)finalvalue); 

return 0; 
} 
+0

Hé, s'il vous plaît exécuter Valgrind la même façon que vous avez été, mais aussi avec le '--track-origins = yes' et collez la sortie dans la question. Aussi, vous pouvez utiliser 'gdb' pour inspecter le programme avec' --db-attach = yes' – alternative

+0

Quelle ligne est la ligne 69 dans libdictionary.c? Quelle est la ligne 84 dans la partie2.c? – alternative

+0

84 dans part2.c: s = dictionary_get (& dictionary, "e"); 69 dans libdict.c: int dictionary_parse (dictionnaire_t * d, char * valeur_clé) { – newprogrammer

Répondre

-2

Si votre programme fonctionne correctement, ne vous souciez pas de ces avertissements. J'ai vu l'avertissement de saut conditionnel sur des programmes qui fonctionnent autrement parfaitement. Cela a probablement à voir avec le code d'assemblage généré par le compilateur et pas directement lié à votre code.

+0

-1 Il n'y a absolument aucune raison de supposer que c'est un faux positif. Il devrait être inspecté car il pourrait facilement introduire une erreur plus tard. – alternative

+0

@mathepic: Je n'ai jamais vu cet avertissement spécifique causer un problème. Les compilateurs peuvent faire des choses étranges lors de l'optimisation du code, ce qui risque d'être un effet secondaire. – casablanca

+0

Normalement Valgrind est exécuté sur du code non optimisé (-g -O0) – alternative

1

lignes comme

char key_word[key_length]; 

look très suspect. Je ne sais pas ce que vous en ferez plus long, mais créer un tableau temporaire de longueur variable pour les choses qui devraient être persistantes plus longtemps que l'appel de la fonction semble très étrange.

En outre, le tableau de longueur variable n'inclut pas la fin '\0'.

1

Vous ne terminez pas correctement les chaînes de caractères key_word et value_word et cette erreur semble se propager. Cette boucle est le problème:

for(j=0;j<key_length;j++){ 
    key_word[j] = *colon; 
    colon++; 
} 

Il copie key_length caractères dans key_word, mais aucun de ces caractères copiés est un terminateur nul. Vous pouvez résoudre le problème en ajoutant un octet supplémentaire pour key_word:

char key_word[key_length + 1]; 

puis en ajoutant ceci après la boucle for():

key_word[key_length] = '\0'; 

Il n'y a pas non plus besoin de créer des copies en finalkey et finalvalue (qui avoir le mauvais type, de toute façon - c'est pourquoi vous finissez par avoir besoin de tous ces moulages laids). Donc dans l'ensemble, il ressemblerait à ceci:

char key_word[key_length + 1]; 
char value_word[value_length + 1]; 

for (j = 0; j < key_length; j++) { 
    key_word[j] = *colon; 
    colon++; 
} 
key_word[key_length] = '\0'; 

space++;  

for(k = 0; k < value_length; k++) { 
    value_word[k] = *space; 
    space++; 
} 
value_word[value_length] = '\0'; 

dictionary_add(d, key_word, value_word); 

Vraiment bien, vous devez simplifier cette fonction en utilisant les installations de string.h.Par exemple, strstr() vous permettra de rechercher la chaîne ": " qui sépare votre clé et la valeur, et memcpy() fait l'équivalent de ces for() boucles:

int dictionary_parse(dictionary_t *d, char *key_value) 
{ 
    char *colon; 
    char *value; 
    int key_length = -1; //Default key length to check for failure 

    colon = strstr(key_value, ": "); 

    if (colon != NULL) { 
     key_length = colon - key_value; // Number of characters before the colon 
     value = colon + 2; // Value is portion of the string after ": " 
    } 

    if (key_length < 1) { 
     return -1; 
    } 

    char key_word[key_length + 1]; 
    memcpy(key_word, key_value, key_length); 
    key_word[key_length] = '\0'; 

    dictionary_add(d, key_word, value); 

    return 0; 
}