Неинициализированные значения Valgrind (создание структуры данных связанного списка) - PullRequest
4 голосов
/ 05 сентября 2010

Я создал класс связанного списка, но эта функция генерирует ошибки valgrind на основании того, что в этой функции есть условный переход, основанный на неинициализированном значении. Я не совсем уверен, что мне нужно сделать, чтобы это исправить.

По существу, существует класс узлов для связанного списка, и он повторяет все узлы, проверяя, соответствует ли параметр ключа ранее существующему узлу и возвращает ли он значение.

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;
}    

Есть идеи?


Я пересмотрел источники отслеживания valgrind, и это вывод:

==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)

Похоже, это может происходить из dictionary_parse, поэтому я тоже опубликую эту функцию.

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;
}

Ответы [ 3 ]

1 голос
/ 05 сентября 2010

Линии как

char key_word[key_length];

выглядит очень подозрительно.

Я не знаю, что вы будете делать с ними дальше, но создание временного массива переменной длины для вещей, которые должны сохраняться дольше, чем вызов функции, кажется очень странным.

Кроме того, массив переменной длины не включает завершающий '\0'.

1 голос
/ 06 сентября 2010

Вы неправильно завершаете строки в key_word и value_word должным образом, и эта ошибка, по-видимому, распространяется.Этот цикл является проблемой:

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

Он копирует key_length символов в key_word, но ни один из этих скопированных символов не является нулевым терминатором.Вы можете решить эту проблему, добавив один дополнительный байт к key_word:

char key_word[key_length + 1];

Затем добавьте это после цикла for():

key_word[key_length] = '\0';

Также нет необходимости создаватькопии в finalkey и finalvalue (которые, во всяком случае, имеют неправильный тип - вот почему вам в конечном итоге понадобятся все эти уродливые приведения).Таким образом, в целом это будет выглядеть так:

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);

Действительно, вы должны упростить эту функцию, используя средства из string.h.Например, strstr() позволит вам искать строку ": ", которая разделяет ваш ключ и значение, а memcpy() делает эквивалент этих циклов for():

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;
}
0 голосов
/ 05 сентября 2010

Если ваша программа работает правильно, не беспокойтесь об этих предупреждениях. Я видел предупреждение об условных переходах в программах, которые в остальном работают отлично. Вероятно, это связано с ассемблерным кодом, сгенерированным компилятором и не имеющим прямого отношения к вашему коду.

...