C trie节点重新分配导致分段错误

C trie node reassignment causing segmentation fault

我正在尝试实现拼写检查器,其中一步是将字典加载到 trie 结构中。我已经使用 GDB 确定,根据我的理解,每次我尝试将 current->children 分配给一个值时都会遇到分段错误。底部的完整代码,但有问题的方法:

bool load(const char* dictionary)
{
    FILE* dic = fopen(dictionary, "r");

    if(dic == false)
    {
        return false;
    }

    root = calloc(27, sizeof(node));
    node* current = NULL;
    /**for(int i=0;i<27;i++)
    {
        current->children[i]=NULL;
    }*/ //this will be the location of the segmentation fault if uncommented
    int a = 0;

    while((a = fgetc(dic)) != EOF)
    {
        if (a == '\n')
        {
            //this is the end of a word
            if(!current->is_word)
            {
                //duplicate case
                current->is_word = true;
                wordcounter++;
            }
            current = root;        
        }
        else
        {
            if(current->children[a-'a'] == NULL)
            {
                current->children[a-'a'] = calloc(27,sizeof(node));
            }
            current = current->children[a-'a'];
        }
    }
    if(current!= root && !current->is_word)
    {
        current->is_word = true;
        wordcounter++;
    }

    fclose(dic);
    return true;
}

那里有注释代码,我在检查了 Whosebug 上的其他几个答案后尝试实现,但这只会导致在 for 循环中发生分段错误。否则,它出现在 if(current->children[a-'a']==NULL){...}

这里发生了什么?我以为 calloc() 自动将分配的内存设置为 0?我触及了哪些不该触及的记忆?

下面是完整的 .c:

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

#include "dictionary.h"

typedef struct node
{
    bool is_word;
    struct node* children[27];
}
node;

node* root;
int wordcounter=0; 

 //Returns true if word is in dictionary else false.

bool check(const char* word)
{
    node* current = root;
    int b = 0;

    while(word[b] != '\n')
    {
        int letter = tolower(word[b]);

        if(letter == '\'')
        {
            return false;
        }

        if(current->children[letter-'a'] != NULL)
        {
            current = current->children[letter-'a'];
            b++;
        }
        else
        {
            return false;
        }
    }

    if(current->is_word == true)
    {
        return true;
    }   
    return false;
}


 // Loads dictionary into memory.  Returns true if successful else false.
bool load(const char* dictionary)
{
    FILE* dic = fopen(dictionary, "r");

    if(dic == false)
    {
        return false;
    }


    root = calloc(27, sizeof(node));
    node* current = NULL;
    /**for(int i=0;i<27;i++)
    {
        current->children[i]=NULL;
    }*/
    int a = 0;

    while((a = fgetc(dic)) != EOF)
    {
        if (a == '\n')
        {
            //this is the end of a word
            if(!current->is_word)
            {
                //duplicate case
                current->is_word = true;
                wordcounter++;
            }
            current = root;        
        }
        else
        {
            if(current->children[a-'a'] == NULL)
            {
                current->children[a-'a'] = calloc(27,sizeof(node));
            }
            current = current->children[a-'a'];
        }
    }
    if(current!= root && !current->is_word)
    {
        current->is_word = true;
        wordcounter++;
    }

    fclose(dic);
    return true;
}


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


 //Unloads dictionary from memory.  Returns true if successful else false. 
void memFree(node* current)
{
    for(int i = 0; i < 27; i++)
    {
        if(current->children[i] !=NULL)
        {
            memFree(current->children[i]);
        }
    }
    free(current);
}

bool unload(void)
{
    memFree(root);    
    return true;
}

错误发生是因为您正在初始化 current = NULL,然后取消引用它 (current->children)。这是一个直接的空指针取消引用。

查看其余代码,您可能打算这样做

node *current = root;

相反。