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

问题描述 投票:0回答:3

无法弄清楚这段代码有什么问题以及为什么我会收到此错误。 c:106 是我标记的行。我认为问题出在上一行的空检查中的 n 值。 这意味着从表中传递的任何内容都是问题?我认为。 第二个函数是加载表的地方。但没有看到任何问题。 刚刚丢了。

    ==6929== Conditional jump or move depends on uninitialised value(s)
    ==6929==    at 0x4012C1: unload (dictionary.c:106)
    ==6929==    by 0x400E09: main (speller.c:152)
    ==6929==  Uninitialised value was created by a heap allocation
    ==6929==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==6929==    by 0x4011B5: load (dictionary.c:71)
    ==6929==    by 0x400964: main (speller.c:40)
    ==6929== 


// 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 = 676;

// Hash table
node *table[N];
int wc = 0;
// Returns true if word is in dictionary else false
bool check(const char *word)
{
    char c[LENGTH + 1];
    node *n =table[hash(word)];
    while (n != NULL)
    {
        if (strcasecmp(n->word, word) ==0)
        {
            return true;
            
        }
        n = n->next;
    }
    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    int tally = 0;
    int j = 0;
    while (word[j] != '\0')
    {
        char letter = tolower(word[j]);
        tally += letter - 'a';
        j++;
    }
    return tally % N;
}

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    FILE *f = fopen(dictionary, "r");
    if(f == NULL)
    {
        return false;
    }
    char t[LENGTH + 1];
    
    while(fscanf(f, "%s\n", t) != EOF)
    {
        node *n = NULL;
        n = malloc(sizeof(node));
        if (n == NULL)
        {
            return false;
        }
       strcpy(n->word, t);
       int x = hash(t);
      
      if (table[x] == NULL)
      {
          table[x] = n;
      }
      else
      {
          n->next = table[x];
          table[x] = n;
      }
       wc++;
    }
    fclose(f);
    return true;
}

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

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
    node *n = NULL;
     for (int i = 0; i < N; i++)
    {
        n = table[i];
        while(n != NULL )
        {
            node *x = n;
            n = n->next;
            free(x);
        }
        table[i] = NULL;
    }
    free(n);
    return true;
}
c pointers
3个回答
1
投票

当 valgrind 说错误位于特定行时,有时它实际上可能位于上一行或下一行。

这里就是这种情况。在第 105 行,有

n != NULL
行。
n
尚未初始化,因此您有未定义的行为。请检查
table
是如何初始化的(代码中未显示)。

最可能导致错误的原因是:您对数组进行了 malloc 但尚未对其进行初始化,或者将值初始化为

X<N
,然后从索引
0
N
访问数组,导致访问不正确对于
]X,N]

编辑:更新代码后,很明显它至少包含以下问题:

  • table
    通过循环
    while(fscanf(f, "%s\n", t) != EOF)
    进行初始化。 = 但用
    while(fscanf(f, "%s\n", t) != EOF)
    解析。假设您的领域中有 X 领域,如果
    X<N
    呢?
    X>N
  • if (table[x] == NULL){table[x] = n;}
    table[x]->next
    仍未初始化

我应该对表使用 calloc 吗?

这是有可能的。但您也可以通过使用 malloc 正确初始化数组来使其工作。两种可能性都是可行的。

总的来说,我认为您的代码不必要地复杂,可以大大简化。您可能想要重构它,而不仅仅是纠正错误。


0
投票

以下建议代码:

  1. 干净地编译
  2. 包含我对 OP 问题所做的大部分评论

现在是拟议的代码;

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>


#define LENGTH 50

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

// Number of buckets in hash table
#define N 676

// Hash table
node *table[N] = {NULL};
unsigned wc = 0;


// Hashes word to a number
unsigned int hash(const char *word)
{
    unsigned tally = 0;
    int j = 0;
    while (word[j] != '\0')
    {
        int letter = tolower(word[j]);
        tally += (unsigned)letter - 'a';
        j++;
    }
    return tally % N;
}


// Returns true if word is in dictionary else false
bool check(const char *word)
{
   // char c[LENGTH + 1];
    node *n =table[hash(word)];
    while (n != NULL)
    {
        if (strcasecmp(n->word, word) ==0)
        {
            return true;
            
        }
        n = n->next;
    }
    return false;
}


// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    FILE *f = fopen(dictionary, "r");
    if(f == NULL)
    {
        return false;
    }

    char t[ LENGTH + 1 ];
    
    while( fscanf( f, "%49s", t ) == 1 )
    {
        node *n = NULL;
        n = malloc(sizeof(node));
        if (n == NULL)
        {
            return false;
        }
        
        strcpy( n->word, t );
        unsigned x = hash(t);
      
        if (table[x] == NULL)
        {
            table[x] = n;
        }
      
        else
        {
            n->next = table[x];
            table[x] = n;
        }
      
        wc++;
    }
    fclose(f);
    return true;
}

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

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

0
投票

您在代码中的某处创建了一个指针,但未初始化 要解决这个问题,你必须给指针一个初始值,甚至是NULL

比如我代码中的load函数如下:

// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
    // Open dictionary
    FILE *file = fopen(dictionary, "r");
    if (file == NULL)
    {
        return false;
    }

    // Navigate dictionary word by word
    char word[LENGTH + 1];
    while (fscanf(file, "%s", word) == 1)
    {
        // Initialize new node
        node *new_node = malloc(sizeof(node));
        if (new_node == NULL)
        {
            // Free other nodes in table
            unload();
            return false;
        }

        // Set word of new node
        strcpy(new_node->word, word);

        // Calculate hash code of word
        int hash_code = hash(word);

        // Check first node of hash table
        if (table[hash_code] == NULL)
        {
            table[hash_code] = new_node;
            new_node->next = NULL;
            word_count++;
        }
        else
        {
            new_node->next = table[hash_code];
            table[hash_code] = new_node;
            word_count++;
        }
    }

    // Close dictionary file
    fclose(file);
    return true;
}

注意 if(table(hash_code) == NULL) 语句。 我new_node->next = NULL;我添加了。

© www.soinside.com 2019 - 2024. All rights reserved.