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

发布于 2024-09-17 18:45:10 字数 2785 浏览 7 评论 0原文

我创建了一个链表类,但该函数会产生 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;
}

I've created a linked list class, but this function is producing valgrind errors based saying that there is a conditional jump based upon an uninitialized value in this function. I'm not exactly sure what I need to do to fix it.

Essentially there is a node class for the linked list and this is iterating over all the nodes checking if the key parameter matches a pre-existing node and if it does it returns the value.

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

Any ideas?


I've reexamined with valgrind tracking origins and this is the output:

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

It looks like this might be coming from dictionary_parse so I'll post that function too.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

十六岁半 2024-09-24 18:45:10

像这样的线条

char key_word[key_length];

看起来非常可疑。

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

另外,可变长度数组不包含终止符'\0'

Lines like

char key_word[key_length];

look highly suspicious.

I don't know what you do with these further along, but creating a temporary variable length array for things that should be persistent for longer than the function call seems very strange.

Also, the variable length array does not include the terminating '\0'.

合约呢 2024-09-24 18:45:10

您没有正确地以 null 终止 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;
}

You are not properly null-terminating the strings in key_word and value_word, and this error is apparently propagating through. This loop is the problem:

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

It copies key_length characters into key_word, but none of those copied characters is a null-terminator. You can fix the problem by adding one extra byte to key_word:

char key_word[key_length + 1];

Then adding this after the for() loop:

key_word[key_length] = '\0';

There is also no need to create the copies in finalkey and finalvalue (which have the wrong type, anyway - which is why you end up needing all those ugly casts). So overall it would look like this:

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

Really though, you should simplify this function using the facilities from string.h. For example, strstr() will let you search for the ": " string that separates your key and value, and memcpy() does the equivalent of those for() loops:

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;
}
ぺ禁宫浮华殁 2024-09-24 18:45:10

如果您的程序工作正常,则不必担心这些警告。我见过程序上的条件跳转警告,否则这些程序可以完美运行。它可能与编译器生成的汇编代码有关,与您的代码没有直接关系。

If your program works correctly, don't bother about those warnings. I've seen the conditional jump warning on programs that otherwise work perfectly. It probably has to do with the assembly code generated by the compiler and not directly related to your code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文