Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 未初始化的值是由堆分配创建的_C_Malloc_Hashtable_Valgrind - Fatal编程技术网

C 未初始化的值是由堆分配创建的

C 未初始化的值是由堆分配创建的,c,malloc,hashtable,valgrind,C,Malloc,Hashtable,Valgrind,我正在尝试使用哈希表实现一个单词词典,因此我需要将其设置为全局,并在我的一个头文件中声明它 extern node** dictionary; 节点在哪里 typedef struct node { char* word; struct node* next; } node; 然后在另一个定义函数的文件中,我包含了带有字典声明的头文件,并且在顶部添加了 node** dictionary; 然后在实际加载字典的函数中,我首先为链表分配内存,链表将构成哈希表 bool loa

我正在尝试使用哈希表实现一个单词词典,因此我需要将其设置为全局,并在我的一个头文件中声明它

extern node** dictionary;
节点在哪里

typedef struct node
{
    char* word;
    struct node* next;
} node;
然后在另一个定义函数的文件中,我包含了带有字典声明的头文件,并且在顶部添加了

node** dictionary;
然后在实际加载字典的函数中,我首先为链表分配内存,链表将构成哈希表

bool load(const char* dict_file)
{
    dictionary = malloc(sizeof(node*) * LISTS);

    FILE* dict = fopen(dict_file, "r");

    if(dict == NULL)
        return false;

    char buffer[MAX_LEN + 2];

    size_dict = 0;

    while(fgets(buffer, MAX_LEN + 2, dict) != NULL)
    {
        node* new_node = malloc(sizeof(node));

        int len = strlen(buffer);

        new_node->word = malloc(sizeof(char) * (len));

        //avoid \n
        for(int i = 0; i < len - 1; i++)
            new_node->word[i] = buffer[i];

        new_node->word[len - 1] = '\0';

        new_node->next = NULL;

        int index = hash(buffer);

        new_node->next = dictionary[index];

        dictionary[index] = new_node;

        size_dict++;
    }

    if (ferror(dict))
    {
        fclose(dict);
        return false;
    }

    fclose(dict);
    return true;
}
bool加载(const char*dict_文件)
{
dictionary=malloc(sizeof(node*)*列表);
文件*dict=fopen(dict_文件,“r”);
if(dict==NULL)
返回false;
字符缓冲区[最大长度+2];
尺寸=0;
while(fgets(缓冲区,最大长度+2,dict)!=NULL)
{
node*new_node=malloc(sizeof(node));
int len=strlen(缓冲区);
新建节点->word=malloc(sizeof(char)*(len));
//避免\n
对于(int i=0;i字[i]=缓冲区[i];
新建节点->单词[len-1]='\0';
新建节点->下一步=空;
int index=散列(缓冲区);
新建_节点->下一步=字典[索引];
字典[索引]=新的_节点;
大小_dict++;
}
if(铁磁(dict))
{
fclose(dict);
返回false;
}
fclose(dict);
返回true;
}

所以程序工作正常,然后我释放所有分配给字符串和节点的内存,当我运行valgrind(一个检测内存泄漏的调试器)时,它说不可能有内存泄漏,但是它说有一个错误,未初始化的值是由堆分配创建的,并将我重定向到为
dictionary
分配内存的那一行,我在上面写的加载函数的第一行。
我做错了什么?我想我全局使用
字典的方法是错误的,那么有人能建议其他方法来保持它的全局性并避免这个错误吗?

分配给
字典的堆分配使用
malloc
,它不会初始化返回的字节。因此,您发布的代码中的
dictionary
最终成为一个未初始化指针数组。假设您继续以valgrind知道是错误的方式使用这些指针


解决这个问题的一个简单方法是使用
calloc
而不是
malloc
,因为它会为您将返回的字节归零。或者,使用
memset
自己将字节归零。

在更新的代码中,使用未初始化的指针:

dictionary = malloc(sizeof(node*) * LISTS);

// .... code that does not change dictionary[i] for any i

new_node->next = dictionary[index];   // use uninitialized pointer
正如人们已经写过的那样,只有在进入此循环之前将所有指针预先设置为
NULL
时,这才有效:

dictionary = malloc(sizeof(node*) * LISTS);
if ( !dictionary ) {
    return false;
}

for (size_t i = 0; i < LISTS; ++i) {
    dictionary[i] = NULL;
}
dictionary=malloc(sizeof(node*)*列表);
如果(!字典){
返回false;
}
对于(大小i=0;i
我写的地方//代码。。。在load函数中,我实际上跳过了60行代码,我从一个文件中逐字加载,为每个单词创建一个新节点,并使
字典
指向的节点*成为指向这些节点的指针,以及我为其分配内存的所有其他节点*都实际使用,以确保程序正确运行,节点表示的单词rapresents被正确地分布在节点*的数组中,然后freedUsing
calloc
隐藏了这样一个事实:您没有在某个地方初始化某个东西,除非您想使用
calloc
显式初始化为
0
,否则它隐藏了另一个问题。这个“答案”只是猜测valgrind在抱怨什么。。。这几乎肯定是错误的。注意:用calloc或memset将指针归零是未定义的行为。@Jim Balter肯定“用calloc或memset将指针归零”不是未定义的行为。代码稍后对这些“归零”指针所做的操作具有未定义的行为潜力。您显示的代码不会再现错误,因此可能是由于您没有向我们显示的其他内容。但我这样做只是因为它只将我发送到此行,下面的代码只是逐字读取文件,为每个单词创建一个节点,并在适当的链表中选择每个节点(其中26个,节点的位置取决于它所代表的单词的第一个字母)。问题出在代码的其余部分,您为什么不发布它?我正试图帮助您,但其余的代码是必需的。请将您的代码简化为显示问题的最小示例。你看到代码了吗。您的行
new\u node->next=NULL
是多余的,因为您随后会直接覆盖它。是的,我知道,它应该用于字典中的每个节点*,否则最后一个节点指向某个垃圾值intead为NULL,谢谢。