Valgrind未初始化的值(制作链表数据结构)

时间:2010-09-05 16:42:33

标签: c list linked-list valgrind

我已经创建了一个链表类,但是这个函数正在生成valgrind错误,这个错误基于这个函数中基于未初始化值的条件跳转。我不确定我需要做些什么来修复它。

本质上,链表有一个节点类,这是迭代所有节点,检查key参数是否与预先存在的节点匹配,如果是,则返回值。

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 个答案:

答案 0 :(得分:1)

这样的行
char key_word[key_length];

看起来非常可疑。

我不知道你对这些做了什么,但为那些应该持续比函数调用更长的事情创建一个临时变量长度数组似乎很奇怪。

此外,可变长度数组不包括终止'\0'

答案 1 :(得分:1)

您未正确终止key_wordvalue_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';

也无需在finalkeyfinalvalue中创建副本(无论如何都有错误的类型 - 这就是为什么你最终需要所有那些丑陋的演员表)。所以整体看起来像这样:

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

答案 2 :(得分:-2)

如果您的程序正常运行,请不要理会这些警告。我已经看到了程序上的条件跳转警告,否则它们会完美运行。它可能与编译器生成的汇编代码有关,而与代码没有直接关系。