Valgrind + C:条件跳转或移动取决于未初始化的值
Valgrind + C: conditional jump or move depends on uninitialised value(s)
我收到这个错误:
Conditional jump or move depends on uninitialised value(s)
我的意思是,我用于条件语句的值未初始化。但是,我相信要初始化的值。我不确定到底是什么问题。帮助将不胜感激。
该代码用于 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;
}
}
问题是因为这段代码:
for (int i = 0; i < LINES; i++)
{
if (add_word(words[i]) == false)
最终将阅读 words
中所有前 LINES
个条目。然而在这个早期的代码中:
for (int i = 0; i < LINES && fgets(buffer, LENGTH * sizeof(char), fp); i++)
你在fgets
失败时停止,如果i < LINES-1
在那一点,这意味着words
中的一些指针保持未初始化。然后你的 valgrind 错误来自 add_word(words[i])
和未初始化的指针。
要解决此问题,您可以先初始化所有指针,或者记住第一个循环结束时 i
的值,并使用相同的值结束第二个循环。
顺便说一句 if (strlen(buffer) <= LENGTH)
是多余的。 fgets
调用已经保证了这一点,因为您指定了 LENGTH
.
的缓冲区大小
我收到这个错误:
Conditional jump or move depends on uninitialised value(s)
我的意思是,我用于条件语句的值未初始化。但是,我相信要初始化的值。我不确定到底是什么问题。帮助将不胜感激。
该代码用于 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;
}
}
问题是因为这段代码:
for (int i = 0; i < LINES; i++)
{
if (add_word(words[i]) == false)
最终将阅读 words
中所有前 LINES
个条目。然而在这个早期的代码中:
for (int i = 0; i < LINES && fgets(buffer, LENGTH * sizeof(char), fp); i++)
你在fgets
失败时停止,如果i < LINES-1
在那一点,这意味着words
中的一些指针保持未初始化。然后你的 valgrind 错误来自 add_word(words[i])
和未初始化的指针。
要解决此问题,您可以先初始化所有指针,或者记住第一个循环结束时 i
的值,并使用相同的值结束第二个循环。
顺便说一句 if (strlen(buffer) <= LENGTH)
是多余的。 fgets
调用已经保证了这一点,因为您指定了 LENGTH
.