代码之家  ›  专栏  ›  技术社区  ›  Sam Phillips

Valgrind+C:条件跳转或移动取决于未初始化的值

  •  -1
  • Sam Phillips  · 技术社区  · 7 年前

    我遇到了这个错误:

    条件跳转或移动取决于未初始化的值

    该代码用于CS50第5周的作业,用于存储一个字典,可以向其中添加值,并且可以用于检查文本的拼写错误。我正在尝试存储字典条目。

    多亏了我在这里得到的帮助,我才能够解决之前出现的错误。我现在将最小示例更改为更接近真实情况(现在它从名为“dictionary/small”的文件中获取单词值,而不是硬编码数组),现在我遇到了另一个问题。 Valgrind指向线路

    if (word == NULL || strcmp(word, "") == 0)
    

    bool add_word(char *word) . 它给出了以下错误:

    ==5452== Use of uninitialised value of size 8
    ==5452==    at 0x4C2F1B1: strcmp (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==5452==    by 0x400B4C: add_word (test.c:81)
    ==5452==    by 0x400AA3: load (test.c:64)
    ==5452==    by 0x4008C6: main (test.c:26)
    ==5452==  Uninitialised value was created by a stack allocation
    ==5452==    at 0x4008E4: load (test.c:30)
    

    代码如下:

    #include <stdio.h>
    #include <stdbool.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define LINES 45
    #define LENGTH 143092
    
    typedef struct node
    { 
        bool is_word;
        struct node *children[27];
    }
    node;
    
    bool load(const char *dictionary);
    bool unload(void);
    bool add_word(char *word);
    int char_to_child(char c);
    char *strdup(const char *s);
    
    node *root;
    
    int main(void)
    {
        load("dictionaries/small");
    }
    
    bool load(const char *dictionary)
    {
        char *words[LINES];
    
        FILE *fp = fopen(dictionary, "r");
        if (fp == 0)
        {
            return false;
        }
    
        char buffer[LENGTH + 1];
        for (int i = 0; i < LINES && fgets(buffer, LENGTH * sizeof(char), fp); i++)
        {
            words[i] = NULL;
            if (strlen(buffer) <= LENGTH)
            {
                words[i] = strdup(buffer);
            }
        }  
        fclose(fp);     
    
        // create a try and add the words
        root = malloc(sizeof(node));
        if (!root)
        {
            return false;
        }
        root->is_word = NULL;
        for (int i = 0; i < 27; i++)
        {
            root->children[i] = NULL; 
        }
    
        for (int i = 0; i < LINES; i++)
        {
            if (add_word(words[i]) == false)
            {
                return false;
            }
            free(words[i]);
        }
    
        return true;
    }
    
    bool add_word(char *word) {
        node *ptr = root;
    
        if (ptr == NULL)
        {
            return false;
        }
        if (word == NULL || strcmp(word, "") == 0)
        {
            return false;
        }
    
        for (size_t i = 0; i < strlen(word); i++)
        {
            int letter = char_to_child(word[i]);
    
            if (letter < 27)
            {
                if (ptr->children[letter] == NULL)
                {
                    node *new_node;
                    new_node = malloc(sizeof(node));
                    if (!new_node)
                    {
                        return false;
                    }
                    new_node->is_word = false;
                    for (int j = 0; j < 27; j++)
                    {
                        new_node->children[j] = NULL;
                    }
    
                    ptr->children[letter] = new_node;
                }
                else
                {
                    if (ptr->children[letter]->is_word != true)
                    {
                        ptr->children[letter]->is_word = false;
                    }
                }
                ptr = ptr->children[letter];
            }
        }
        ptr->is_word = true;
    
    
        return true;
    }
    
    int char_to_child(char c)
    {
        if (c >= 'A' && c <= 'Z')
        {
            return c - 'A';
        }
        else if (c >= 'a' && c <= 'z')
        {
            return c - 'a';
        }
        else if (c == '\'')
        {
            return 26;
        }
        else 
        {
            return 27;
        }
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   M.M    7 年前

    for (int i = 0; i < LINES; i++)
    {
        if (add_word(words[i]) == false)
    

    最终会阅读第一部分的所有内容 LINES words . 然而,在此早期代码中:

    for (int i = 0; i < LINES && fgets(buffer, LENGTH * sizeof(char), fp); i++)
    

    你什么时候停下来 fgets 失败,如果 i < LINES-1 add_word(words[i])

    要解决这个问题,可以先初始化所有指针,或者记住 i 从第一个循环结束,并使用相同的值结束第二个循环。

    顺便提一下 if (strlen(buffer) <= LENGTH) FGET 调用已经保证了这一点,因为您将缓冲区大小指定为 LENGTH