Valgrind:有条件的跳跃或移动取决于未初始化的值。在较长的数组中用 '\0' 终止字符串不够吗?

Valgrind: Conditional jump or move depends on uninitialised value(s). Is not terminating a string inside a longer array with '\0' enough?

cs50的第5题,拼写,要求实现一些词典功能。 我用 valgrind 收到这个警告:

==393== Conditional jump or move depends on uninitialised value(s)
==393==    at 0x49DB143: tolower (ctype.c:46)
==393==    by 0x483F864: strcasecmp (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==393==    by 0x4019CF: check (dictionary.c:42)
==393==    by 0x401603: main (speller.c:114)
==393==  Uninitialised value was created by a heap allocation
==393==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==393==    by 0x401AF8: load (dictionary.c:82)
==393==    by 0x40129E: main (speller.c:40).

这是我的 dictionary.c 文件,其中包含辅助函数。

// Implements a dictionary's functionality

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dictionary.h"
#include <strings.h>

// Represents a node in a hash table
typedef struct node
{
    char word[LENGTH + 1];
    struct node *next;
}
node;

// Number of buckets in hash table
const unsigned int N = 1;

unsigned int siz = 0;
// Hash table
node *table[N];
/*
for (int i = 0; i < N; i++)
{
    table[i]->next
}
*/

// Returns true if word is in dictionary, else false
bool check(const char *word)
{
    // TODO

    int h = hash(word);

    node *ll = table[h];
    while (ll != NULL)
    {

        if (strcasecmp(ll->word, word) == 0)
        {
            printf("len: %lu\n", strlen(ll->word));
            return true;
        }
        ll = ll->next;
    }
    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    // TODO
    return 0;
}

// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
    printf("a\n");
    // TODO
    FILE *input = fopen(dictionary, "r");
    if (input == NULL)
    {
        printf("Could not open file.\n");
        return false;
    }
    printf("b\n");
    char c;
    int i = 0;
    unsigned int h = 0;
    char word[LENGTH + 1];
    node *key = NULL;

    while (fread(&c, sizeof(char), 1, input))
    {

        if (i == 0)
        {
            key = malloc(sizeof(node));
        }

        else if (c == '\n')
        {
            word[i] = '[=11=]';
            i = 0;
            h = hash(word);
            key->next = table[h];
            table[h] = key;
            siz++;
            continue;
        }
        key->word[i] = c;
        i++;

    }
    fclose(input);
    /*
    for (int j = 0; j < N; j++)
    {
        while (table[j] != NULL)
        {
            printf("%s ->\n", table[j]->word);
            table[j] = table[j]->next;
        }
    }
    */
    return true;
}

// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
    // TODO
    return siz;
}

// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
    // TODO
    node *n = NULL;
    node *tmp = NULL;
    for (int i = 0; i < N; i++)
    {
        n = table[i];
        while (n != NULL)
        {
            tmp = n;
            n = n->next;
            free(tmp);
        }
    }
    return true;
}

我认为出现此警告是因为在第 42 行,函数 strcasecmp 试图将字符串 node->word 的某些字符小写,即使在 '\0' 之后也是如此。 事实上,如果我在 load() 中替换,警告就会消失, key = malloc(sizeof(node));key = calloc(1, sizeof(node)); 因为 calloc allocate 并将内存设置为 0.

所以,我的问题是:strcasecmp 是如何工作的?? 在 malloc 场景 ll->word 中,我传递给 strcasecmp 的参数是这样的字符数组“actual_valid_chars \0 垃圾字节直到数组长度:LENGTH”。 在 calloc 场景中,数组是“actual_valid_chars \0 000000...”。

因此,我认为在 malloc 的情况下,我正在将未初始化的内存传递给 strcasecmp,但在这两种情况下我也使用 \0 终止字符串。

strcasecmp() 不应该通过'\0'识别字符串的结尾,即使它在数组的中间? 有人可以向我澄清这些段落吗? 另外,我可以简单地忽略这些警告,还是有更好的做法可以使用?

key->word 在加载函数中不是空终止的。 char 数组 word 是,尽管它从未被填充。